Page Numbers: Yes X: 530 Y: 10.5" First Page: 11
Line Numbers: No Modulus: 5 Page-relative
Heading:
Programmer’s Guide to Orbit, the ROS Adapter, and the Dover Printer
1.5 Orbit Hardware Functions
There are various kinds of transfers of information between the Alto microprocessor and Orbit; each can transfer up to 16 bits of information. Although the transfers are actually accomplished with microcode functions interpreted by Orbit, the functions themselves are used by higher-level language programmers as well. The list below gives each transfer a name (of the form Orbitxx); the description assumes a 16-bit value is transferred (refer to Figure 1-6 for a tabular summary of this information):
Functions for status and control
OrbitControl. This function transfers 16 bits of control information to Orbit. The fields of this value are as follows:
FieldBitsFunction
auxControl0-7This 8-bit field has two different interpretations, depending on the setting of the WHICH field (q.v.).
ESS8This bit must be 1 to enable changing the SLOTTAKE setting (q.v.).
SLOTTAKE9This bit setting, enabled by ESS above, controls the output buffer logic. Normally (SLOTTAKE=0), Orbit will not honor video data requests coming from the adapter. As soon as SLOTTAKE is set to 1, however, output data will be passed to the adapter when it demands it.
clrBEHIND11This bit clears the BEHIND indicator (see below).
setGOAWAY12This bit controls microcode wakeups, and should normally be 0. (See section on microcoding for more information.)
WHICH13This bit controls the use to which the 8-bit auxControl field is put. If WHICH=0, auxControl is interpreted as an address (range 0 to 63) into the adapter status memory: when OrbitStatus is next interrogated, 4 status bits (with numbers 4*auxControl to 4*auxControl+3) will be reported. If WHICH=1, auxControl is used to set FA.
CLRFRESH14This bit controls refresh logic, and should normally be 0. (See section on microcoding for more information.)
RESET15This bit, if 1, will reset Orbit entirely. A reset performs at least the following functions: FA←0, SLOTTAKE←0, band buffer A is assigned to the image buffer, the status and control dialogues with the adapter are reset.
OrbitStatus. This function reads 16 bits of status information from Orbit into the Alto. The starred status bits below (*) are generated by firmware only in some situations. The notation a←OrbitStatus denotes the hardware status-reading function, and does not include the firmware status bits. The notation a←OrbitStatus+FirmwareStatus denotes the full status report. The status fields are:
FieldBitsFunction
IACSmc0*This bit is 1 if Orbit is "in a character segment," i.e., if Orbit needs more OrbitFontData transfers in order to complete image-generation for the current character. (This bit is not actually reported by Orbit to the Alto in this way, but is inserted by the "standard microcode.")
TIMEOUTmc1*(This bit is not actually reported by Orbit to the Alto, but is inserted by the "standard microcode." See the description of ProgramGeneratePage, above).
unstableROSmc2*(This bit is not actually reported by Orbit to the Alto, but is inserted by the "standard microcode." See the description of ProgramROSStatus, above).
earlyPageAbortmc3*(This bit is not actually reported by Orbit to the Alto, but is inserted by the "standard microcode.") If, at the end of a band, the adapter has stopped accepting video information, and if the BEHIND bit (below) is set, ProgramGeneratePage terminates early (as if it had timed out), with this bit set.
badBandEntrymc4*(This bit is not actually reported by Orbit to the Alto, but is inserted by the "standard microcode.") The ProgramGeneratePage microcode has encountered a non-character band entry that does not specify a valid operation. It has stored additional diagnostic information in fixed memory locations. This condition should only arise in instances of severe hardware or software faults. Consult the Orbit microcode listings for further information.
badROS8This bit is true if an error of some sort has been detected on the adapter status-reporting line. The adapter status cannot be trusted. The condition will be reset after the first properly-formatted status burst is received from the adapter.
INCON9This bit announces the current band buffer assignments. If it is 0, buffer A is the image buffer, and buffer B is the output buffer. Watching this bit for changes is the proper way to detect "buffer switches."
stableROS10This bit is true if a status burst is not currently arriving from the adapter. If you insist on reading some adapter status that must be from the same burst, you can check this bit before and after a read.
BEHIND11This bit is set when Orbit "gets behind." This will happen if the buffers switch (due to output requests) before the Alto microcode has finished sending the next band of image-generation information to Orbit (finishing is signaled to Orbit by setting GOAWAY).
ROSStatus12-15This field gives 4 bits of status reported by the adapter. See the description of WHICH, above.
Functions for controlling image-generation
There are a number of functions for controlling image generation. There is a reasonably standard sequence of operations for transferring source rasters into Orbit. The first three functions (OrbitHeight, OrbitXY, and OrbitDBCWidthSet) are used to pass to Orbit the four parameters that describe a source raster and its position in the band. The last of these (OrbitDBCWidthSet) sets a flag IACS ("in a character segment") that indicates Orbit is expecting source raster data. Then the OrbitFontData function is used to send words of source raster information to Orbit. After the character is finished (or we run into the edge of the band at x=15), the two functions OrbitDBCWidthRead and OrbitDeltaWC are used to extract from the Orbit hardware the necessary parameters to compose a "left over" entry so that image generation for this character can be resumed in the next band.
OrbitHeight. This command sends to Orbit a 12-bit field (value[4-15]) which is interpreted as the two’s complement of the height of the source raster, in bits.
OrbitXY. This command sets xvalue[0-3] and yvalue[4-15]. It is therefore used to set the starting scan-line within the band (x) and the vertical position of the bottom of the copy of the source raster (y).
OrbitDBCWidthSet. This function has three purposes: First, value[0-3] is used to tell Orbit which bit (0 to 15) of the first word of raster data is the first bit to be examined (i.e., it will play the role of SOURCEBIT for the setting of BAND[x,y], where x and y were set with OrbitXY). Second, value[4-15] is interpreted as the width of the source raster, minus 1. Third, executing this function initializes a mess of logic relating to transferring a source raster to Orbit and sets IACS ("in a character segment"). After the function is executed, it is wise to issue only OrbitFontData functions until the image-generation for this character terminates (i.e, IACS becomes 0). Warning: IACS is cleared by StartIO(4); consequently it is not possible to "single step" Orbit’s character generation.
OrbitFontData. This function is used to send 16-bit raster data words to Orbit, usually in a very tight loop. The loop is exited when IACS becomes 0, that is, when the Orbit hardware counts the width counter down to zero, or when the x counter overflows (i.e., when it would count up from 15 to 16).
OrbitDBCWidthRead. This function returns from Orbit to the Alto a 16-bit value that corresponds to the value set with OrbitDBCWidthSet, but after the image-generation for this character (in this band) has completed. Thus, value[0-3] tells which bit should be the first to be examined when image-generation resumes in the next band. Also, value[4-15] contains the remaining width (minus 1) of the character. If value[4-15]=7777b, there is no remaining width, because the width counter counted down to zero (i.e., the source raster was exhausted).
OrbitDeltaWC. This function returns from Orbit to the Alto the count of the number of full 16-bit words of OrbitFontData that were used during the image-generation for this character (the counter is initialized to 0 when OrbitDBCWidthSet is issued). This allows the Alto program to compute the memory address in the source raster where generation should resume in the next band. (Note: This function is needed because it is too time-consuming to derive the count by calculation. If you really understand Orbit, you will be able to verify that DeltaWC=(Height*SL+DBC)/16, where DBC is the 4-bit value passed to Orbit with OrbitDBCWidthSet, and SL is [if x+Width < 16 then Width else 16−x].)
Functions for communicating with the adapter
Reading adapter status is accomplished with the OrbitControl and OrbitStatus functions (first set the status memory address, then read 4 status bits). Commands are sent to the adapter with:
OrbitROSCommand. This function sends a 16-bit command to the ROS. Another ROS command should not be issued until 60 microseconds have elapsed, to allow time for proper transmission of the command to the ROS.
Miscellaneous functions
OrbitOutputData. This function reads 16 bits of output data from Orbit into the Alto. The sequencing of words of data is described below.
OrbitInk. This function sets 16 bits of INK memory: INK[x,0] through INK[x,15], where x has been previously set with OrbitXY.
1.6 Standard microcode — complete description
The standard microcode was introduced in section 1.4; the description of bootstrapping and of the control table apply here as well. Here we give a complete list of the functions it implements:
ProgramControl (directive=0). Argument1 is passed to Orbit as a control word: OrbitControl ← Argument1.
ProgramOutputData (directive=1). This operation simply reads 16 bits of Orbit output data: Result ← OrbitOutputData.
ProgramHeight (directive=2). This operation sets the Orbit height parameter: OrbitHeight ← Argument1. It also returns a result: Result ← (if image buffer needs refreshing then -1 else 0).
ProgramXY (directive=3). This operation sets the Orbit X and Y registers: OrbitXY ← Argument1.
ProgramDBCWidthSet (directive=4). This operation sets the DBC and Width counters: OrbitDBCWidthSet ← Argument1.
ProgramFontData (directive=5). This operation transfers one word of font data to Orbit: OrbitFontData ← Argument1.
ProgramDeltaWC (directive=6). This operation reads the word counter: Result ← OrbitDeltaWC. Because each function implemented by the standard microcode reports Orbit status on completion, the ProgramDeltaWC function is a fine way to read Orbit status without changing any Orbit state.
ProgramInk (directive=7). This operation transfers a word to the ink memory: OrbitInk ← Argument1.
ProgramDBCWidthRead (directive=8). This operation reads the current settings of the DBC and Width counters: Result ← OrbitDBCWidthRead.
ProgramROSCommand (directive=9). This operation sends 16 bits to Orbit to be forwarded to the adapter as a command: OrbitROSCommand ← Argument1.
ProgramReadBlock (directive=10). This operation is used to read a sequence of OrbitOutputData words. Argument1 gives the number of words to read; Argument2 is the address where the first word should be stored. The function is equivalent to the following code:

for i=0 to Argument1−1 do
Argument2!i ← OrbitOutputData
ProgramCharacter (directive=11). This operation is used to pass a source raster to Orbit at high speed, and can be described as a collection of primitive commands (note that control table entries are used in a way that makes their names meaningless):

OrbitHeight ← Argument1
OrbitXY ← Argument2
OrbitDBCWidthSet ← nBandsMinus1
for i=0 to Abs(LoTable)−1 do
OrbitFontDataFAword!i
Result ← OrbitDBCWidthRead
NewCharPointer ← OrbitDeltaWC

Note that this operation returns two values, one of which is stored in the NewCharPointer word of the control table (a non-standard place). The sign of the LoTable entry is used to choose one of two inner loops (for the "for" loop above): if LoTable>0, the inner loop contains
TASK microprocessor functions; if LoTable<0, no TASKs are included (this is to aid in hardware debugging).
ProgramGeneratePage (directive=12). See section 1.4 for a complete description.
ProgramGenerateBand (directive=13). This function is very similar to ProgramGeneratePage, but will perform the image-generation chores for only one band, and leave the results in the Orbit image buffer: this function does not make arrangements to forward the image information to the ROS adapter. The intention is that the Alto program may want to read the generated image back into Alto memory rather than forwarding it to a ROS immediately.
The arguments to the function are as follows (see section 1.4 for a description of the data structures for fonts, left-overs and band lists):

LoTable = LoTablePointer (left-over pointer, must be even)
FontTable = FontTableX+100000b (pointer to font table, offset by 100000b)
NewCharPointer = BandListPointer−1 (BandListPointer must be even)

The function returns Result ← BandListPointer’-1, where BandListPointer’ is a version of BandListPointer updated by processing all the entries for the one band (i.e., Result will point at the second word of the End-of-Band entry for the processed band). The idea is that
ProgramGenerateBand can be called to generate the next band by setting NewCharPointer to the Result of the current band. (See also the description below concerning refreshing.)
The function ProgramGenerateBand makes no provision for reading the Orbit buffer back into the Alto. This can be accomplished with other Programxx functions.
ProgramROSStatus (directive=14). This operation reads an entire word (16 bits) of ROS status, using OrbitControl and OrbitStatus primitives. If we view the 256 status bits as lying in 16 16-bit words, numbered 0 to 15, then this function stores in Result the current value of status word n, where Argument1 = n * 1024. The firmware status bit unstableROSmc, reported in the OrbitStatus table entry, is zero if all 16 bits of status were extracted from the same status burst emanating from the adapter.
1.7 Refreshing the image buffer
As an image is being prepared in the image buffer, it may be necessary to refresh the buffer in order to keep its contents from changing (this is because the buffer memories are implemented with MOS RAM’s). Reading an image from the output buffer not only clears the buffer but also refreshes it during the readout. When the reading completes, the buffers switch so that the output buffer becomes the image buffer. The image buffer must be refreshed by the microcode every 2 ms. until it is once again switched to become the output buffer.
The Orbit programmer must arrange so that the image buffer is refreshed if it contains valuable data. There are two cases to consider: (1) while a Programxx function is being executed, and (2) between invocations of Programxx functions. Most functions are speedy enough that no provision is made for refreshing. The ProgramGenerateBand and ProgramGeneratePage functions, on the other hand, automatically provide refreshing.
If the contents of the image buffer need to be preserved between invocations of primitive functions, it will be necessary to insure that the buffer is refreshed even while the Alto program is away doing other things (e.g., when the refreshing provided by ProgramGenerateBand is not functioning). To help with this requirement, the standard microcode has provision for performing the refresh duties even when no Programxx function is being executed. Thus, rather than turning off the Alto Orbit-controlling task between functions, the task remains active, waking up and refreshing the image buffer whenever it is appropriate. This refresh idling function can be specified by turning on bit 0 (100000b) in the Directive word of the control table, in addition to specifying a Programxx function number in the directive. In this case, when the function terminates, the image buffer will continue to be refreshed. Enabling the idling activity in no way alters the invocation of the next Programxx function.
1.8 Reading a buffer into the Alto
Orbit has provisions for reading the output buffer back into Alto memory rather than shipping it to the ROS adapter. This is useful for for image-generation that is so complicated it cannot keep pace with the printing device: the buffers can be returned to the Alto, and buffered again on a big disk. A second pass is used to transmit the disk buffers (via Orbit) to the ROS. The read-back is also vital for debugging Orbit.
Basically, the function OrbitOutputData reads 16 bits from the output buffer into the Alto. The standard microcode interfaces ProgramOutputData and ProgramReadBlock are provided to give access to this function.
The programmer needs to be aware of two tricky details concerning readout:
1. There is a 16-bit buffer (ROB) that sits between the addressing mechanism described above and the outside world (the taker of data: the Alto or the ROS adapter). As a result, immediately after the buffers "switch," the ROB contains the last 16-bits of data from the previous buffer (x=15, y=4080 through y=4095). The usual convention is to read out this one last word. This leaves the first word of the new buffer in ROB.
2. The output band buffer will not be refreshed because no readout is in progress. Because the buffer is implemented with dynamic MOS RAM’s, the lack of refreshing will cause errors in the data to appear beginning about 2 ms. after the buffer switch. This data "rotting" happens rather slowly, but is nonetheless irksome. To avoid trouble, reading the output buffer should begin within the alotted 2 ms. after the buffer switch. As soon as reading begins, the reading itself serves to refresh the memory.
The scheme is as follows: (1) The Alto reads the output band buffer entirely (buffer A, say), thereby clearing it and also causing the buffers to switch; (2) Now the Alto invokes image-generation to fill the buffer (A) with an image; (3) The Alto reads the output buffer (B) as quickly as possible, simply to cause the buffers to switch; (4) The Alto reads the output buffer (A) and saves the image. Note that step 4 can also serve the same role as step 1. We could leave FA set to some fixed value throughout these steps, but this will cause step (3) to require more time than necessary. Some detailed analysis shows how to avoid this:
The setting of FA provided by the Alto is examined only when Orbit reads out the last 16 bits of a scan-line, and must prepare to begin reading the next scan-line. If you wish to control FA carefully, you must anticipate the moments at which Orbit will load its address register from FA. The most common case in which careful synchronization is needed is when you wish to induce a buffer switch with minimum effort.
Let us describe the handling of FA for the 4-step example above. Define FAimage to be the FA that corresponds to the image you wish to read. First, we need to get "in sync:"

set Orbit’s FA ← FAimage
until buffers switch do [ read a word from the output band buffer ]
read a final word from the output band buffer (because of ROB)

This sequence guarantees FA has been set to FAimage, and that we are ready to begin reading a buffer. Step 1 (or step 4) becomes:

read (256-FAimage)*16−2 words from the output band buffer
set Orbit’s FA ← 255
read the last two words from the output band buffer

Step 3 then becomes:

read (256-255)*16−2 words from the output band buffer
set Orbit’s FA ← FAimage
read the last two words from the output band buffer
1.9 Microcoding
This section presents some additional information on microcoding the Orbit. It refers generously to preceding sections, in which the basic data transfers (Orbitxx functions) have been described. The reader should be familiar with Alto microcode (see the Alto Hardware Manual), and may wish to refer to the Orbit functional description. The serious reader is urged to retain a copy of the standard microcode at his/her elbow as an example of how things can be done.
Assignment of functions. Each of the Orbitxx functions described above is assigned a value of the Alto F1 or F2 fields: Orbit decodes these fields to decide what to do. Definitions at the beginning of OrbitMc.Mu establish some conventional names for these functions. The assignment is as follows:
OrbitControlF2=15b
OrbitStatusF1=17b *
OrbitHeightF2=12b *
OrbitXYF2=11b
OrbitDBCWidthSetF2=10b
OrbitFontDataF2=13b
OrbitDBCWidthReadF1=15b
OrbitDeltaWCF1=14b
OrbitROSCommandF2=16b
OrbitOutputDataF1=16b
OrbitInkF2=14b
OrbitBlock (see below)F1=3
The starred items (*) may cause microcode branches. OrbitStatus sets NEXT[7] if IACS is not on, i.e., if Orbit is not in a character segment. OrbitHeight sets NEXT[7] if the refresh timer has expired, i.e. if the image buffer needs refreshing.
Whenever one of the microcode functions (Orbitxx) is executed, the Alto clock may not stop during its execution. The microcoder must arrange the microcode so that, for example, memory waits do not occur on cycles in which Orbitxx functions are executed. The standard microcode has comments (//// in the comment field) whenever instructions have been inserted to observe this timing restriction.
Wakeups. Orbit is controlled by a single Alto microtask (task number 1, next lowest priority to the emulator). Consequently, the Orbit hardware must generate a "wakeup signal" to govern the execution of microinstructions in the Orbit task: the wakeup should be generated when the Orbit hardware requires service of some sort.
The wakeup condition is very simply expressed in hardware, but deserves a more discursive treatment here. There are a number of considerations:
1. The RUN flip-flop. We want Orbit’s wakeups to be filtered by a single RUN condition, that says whether Orbit is idle or is expected to be doing things. Whenever the Alto is reset (bootstrapped), the RUN condition is turned off. The emulator program may execute StartIO(4) to turn the RUN condition on (note that StartIO is simply the name of a software function that executes the emulator SIO function). The RUN condition is turned off by the execution of the OrbitBlock function by the Orbit task itself.
2. Executing miscellaneous functions (e.g., OrbitROSCommand). We would like the Orbit task to be normally active (i.e., requesting wakeup) so that various utility functions can be accomplished. When the function terminates, we can always deactivate the Orbit task with OrbitBlock.
3. Performing image generation. Again, we would like the Orbit task to be normally active, so that parameters and source raster data words can be shipped to Orbit at high speed. However, if Orbit’s FIFO that contains font data words (shipped with OrbitFontData) becomes full, the Orbit task should be temporarily suspended until the FIFO entries are processed by Orbit and there is once again room. When image generation for a character segment terminates (IACS becomes 0), we want to get service no matter what the FIFO contains.
4. Waiting for the ROS to take a buffer. After image generation for a band is complete, Orbit usually needs to "wait" until the ROS has emptied the other (output) buffer. During this period, the Orbit task should not be requesting wakeups, so that the Alto microprocessor may be devoted to other tasks. To achieve this "dormant" state, the Orbit task sets the setGOAWAY bit in the control word: this tells Orbit to "go away" until a buffer switch occurs. The buffer switch will turn off GOAWAY, and consequently allow wakeups again.
5. Refreshing the image buffer periodically. If the image buffer memory is to be kept valid, it must be periodically refreshed. Consequently, we need to have a provision for waking up Orbit for refreshing even when Orbit is dormant (waiting for a buffer switch, as in (4) above). For this purpose, there is a REFRESH condition that indicates refreshing is needed: it is set every 2 ms. (approximately), and may be cleared by the CLRFRESH bit in the control word. Even though GOAWAY has been set, Orbit will be awakened when the REFRESH condition becomes true.
Let us summarize the conditions on which wakeups depend and give the wakeup condition itself:
RUNSet by StartIO(4)
Cleared by executing OrbitBlock

IACS
Set by executing OrbitDBCWidthSet
Cleared when the character is finished (i.e., the width
counter becomes 0 or the x counter overflows)
Also cleared by executing StartIO(4) or by reseting Orbit

REFRESH
Set every 2 ms. by a timer
Cleared by the CLRFRESH bit in OrbitControl

GOAWAY
Set by the setGOAWAY bit in OrbitControl
Cleared by a buffer switch or by an Orbit reset
Orbit will request a wakeup if:
RUN and
{ [ (
FIFO has room) or IACS=0 ] and
[
REFRESH=1 or GOAWAY=0 ] }
Refreshing. There is a standard ritual for refreshing the image buffer. Although the technique can be discerned from the addressing mechanism, we shall present it here for convenience. The basic idea is to cycle all the memories by generating a "character" of the right sort, but to leave the memory contents unaltered by using font data words that are zero. The suggested technique is (see the standard microcode for an instance of this technique):
OrbitXY ← 0
OrbitHeight ← 6000b(character is 1024. bits high)
OrbitDBCWidthSet ← 0(character is 1 scan-line wide)
until
IACS=0 do OrbitFontData ← 0
1.10 Algorithm for ProgramGenerateBand and ProgramGeneratePage
The algorithm for the two central functions is best understood by consulting the text for the standard microcode. This section is simply a condensation of some of the information contained in comments in that file. In the description below, notation of the form a←b!c means that memory location b+c is read, and the 16 bits are transferred to destination a.
The microcode consists of three subroutines (DOBAND, TFRCHR, and REFRESH), and a main driver for the functions. DOBAND is responsible for sequencing through a band, calling TFRCHR (transfer a character to Orbit) for each character, and calling REFRESH every 2 ms. The driver for ProgramGenerateBand simply calls DOBAND and returns. The driver for ProgramGeneratePage is somewhat more complicated:
OrbitControl ← 300b (turn on SLOTTAKE)
OrbitControl ← FAword + 4 (WHICH, plus the FA setting)
bandResult ← nBandsMinus1+1

Main loop. First execute any pending adapter command entries.
while nBandsMinus1 > 0 do begin
while (Argument1!0−nBandsMinus1) and 7777b = 0 do begin
a←(Argument1!0 and 30000b)
b←Argument1!1
Argument1 ← Argument1+2
if a = 0 then OrbitROSCommand ← b else
if a = 10000b then begin
OrbitControl ← b
Argument1!−1 ← OrbitStatus
end else
if a = 30000b then wait b/3 microseconds
end

Now call the DOBAND subroutine to compose the image for this band.

call DOBAND
OrbitControl ← 10b (set GOAWAY)
if AdapterStatus.SendVideo = 0 and OrbitStatus.BEHIND = 1 then
return from ProgramGeneratePage with earlyPageAbortmc bit set
if AdapterStatus.(word 8, bit 3) = 1 then bandResult ← nBandsMinus1
a ← Argument2
until bands switch do begin
wait until refreshing needed or bands switch
if a < 0 then return from ProgramGeneratePage with TIMEOUTmc bit set
call REFRESH
a ← a−1
end
nBandsMinus1 ← nBandsMinus1−1
end
Result ← bandResult
return
The DOBAND subroutine is responsible for sequencing through the band lists and leftovers:
DOBAND:LORP←LoTable−1
LOWP←LoTable−1(LOWP is the write pointer for new leftovers)

First, process the left-over list remaining from last time. Each entry is four words long, containing the height, the XY setting (with X=0), the remaining width and the memory address of the first source raster word to send to Orbit. Note that the height and XY information is also saved in registers (HEIGHT, XY) so that TFRCHR can build a new left-over list:

while LORP!1 = 0 do begin
if refreshing needed then call REFRESH
OrbitHeight ← HEIGHT ← LORP!1
OrbitXY ← XY ← LORP!2
OrbitDBCWidthSet ← LORP!3
FONTADR ← LORP!4
call TFRCHR
LORP ← LORP+4
end

Now go through the new character list (band list) for this band, and decode the entries. Character entries are looked up in the font index; rule parameters are simply passed on to Orbit. (Note that the "refreshing needed" test is a part of
OrbitHeight, and is consequently done in a slightly different place in the actual microcode.)

while true do begin
if refreshing needed then call REFRESH
a ← NewCharPointer!1
XY ← NewCharPointer!2
NewCharPointer ← NewCharPointer+2
if a < 0 then begin
OrbitXY ← XY
FONTADR ← FontTable!a
OrbitHeight ← HEIGHT ← FONTADR!0
OrbitDBCWidthSet ← FONTADR!1
FONTADR ← FONTADR+2
end else case a% of begin
case 1: begin
OrbitXY ← XY
FONTADR ← 0
OrbitHeight ← HEIGHT ← NewCharPointer!1
OrbitDBCWidthSet ← NewCharPointer!2
NewCharPointer ← NewCharPointer+2
end
case 4: begin
if a = CurrentCopy then NewCharPointer←NewCharPonter+XY;
repeat the loop
end
case 0: exit the loop
all other cases: return from ProgramGeneratePage with badBandEntrymc bit set
end
call TFRCHR
end

LOWP!1 ← 0
The TFRCHR subroutine transfers a character to Orbit. If the character does not exhaust its width in this band, a left-over entry is made. The variable FONTADR usually contains the address of a source font word, but if it is zero, we are transferring a "rule" to Orbit.
TFRCHR:if FONTADR=0 then begin
until IACS=0 do OrbitFont ← -1
FONTADR ← - OrbitDeltaWC
end else begin
p ← FONTADR
until IACS=0 do begin
OrbitFont ← p!0
p ← p+1
end
end

Now check to see if the charcter requires a left-over (width
=7777b):
p ← OrbitDBCWidthRead and 7777b
if p = 7777b then begin
LOWP!1 ← HEIGHT
LOWP!2 ← XY and 7777b (this sets X←0, but preserves Y)
LOWP!3 ← OrbitDBCWidthRead
LOWP!4 ← FONTADR + OrbitDeltaWC
LOWP ← LOWP+4
end
And finally, the REFRESH subroutine performs the refreshing chore:
REFRESH: OrbitXY ← 0
OrbitHeight ← 6000b
OrbitDBCWidthSet ← 0
until IACS=0 do OrbitFont ← 0