; O R B I T Microcode
;
; Must be fetched from a root microcode file that defines the low-RAM locations, etc.
; See [Ivy]<Spruce>SpruceMc.MU
;
; Location 720b points to a control table (even address) with
; the following entries:
;0
Directive -- tells which function to execute
;1
Argument 1 -- first argument to the function
;2
Argument 2 -- second argument
;
; ...entries below here used only for directive 12 and 13 ...
;3
nBandsM1 -- number of bands (-1) to generate
;
A band is 16. scan-lines
;4
FA -- first read address for output (left half-word)
;5
LoTable -- pointer to left-over table
;
Must be even; must be initialized with @LoTable=0
;6
FontTable -- pointer to table of font characters:
;
(ICC is a mnemonic for ’internal character code’)
;
FontTable!(ICC+100000b) => Fdes (must be even)
;
Fdes!0=-Height (in bits)
;
Fdes!1=Width-1
;
Fdes!2,3,... bit map for character
;7
NewRp -- pointer to list of "new characters" :
;
NewRp!1 is first word and must be even
;
Each entry on NewRp is one of:
;
(a) A character (2 words). First word is ICC+100000b
;
Second word is xInBand (bit 4), Y (bit 12.)
;
XY address is of lower left corner of box.
;
(b) A "rule" (4 words). First word is 1.
;
Second word is xInBand (bit 4), Y (bit 12.) -- same
;
interpretation as for a character.
;
Third word is -Height (in bits). Fourth word is
;
Width-1.
;
(c) A band terminator (2 words, both =0) used to mean
;
that no more information is required for this band.
;
; ...these entries are filled in by the microcode with values ...
;8.
Result -- if a function returns a result, it is placed here
;9.
Status -- records latest Orbit status
;
Some "firmware status" bits are added to the normal Orbit status
;
word:
;
100000b-- Orbit is "in a character segment" (IACS)
;
40000b -- Timeout in Slot band switch wait (Directive=14b)
;
20000B -- ROS status WORD unstable (Directive=16b)
;
10000B -- Microcode got behind and send video went away
;
4000B -- Illegal "band code" in band file entry
;
; Idling. When a function is finished execution, the microcode sets
; location 720b to zero, and will then idle in one of two ways:
;
(a) Normal. The Orbit task is blocked entirely; there is no activity.
;
A StartIO(4) is required to resume processing.
;
(b) Refreshing. The microcode goes "to sleep," but will awake to
;
refresh the Orbit memory (the buffer being written into)
;
periodically. If, upon awakening, a non-zero value is detected
;
in location 720b, it goes off to execute the specified function.
;
Awakening may be hastened by executing StartIO(4)
; (a) is default; turn on 100000b bit in Directive to get (b)
;
;
; F U N C T I O N S
;
; Directive=0: OrbitControl ← argument 1
; Directive=1: result ← OrbitData
; Directive=2: OrbitHeight ← argument 1,
;
result ← (if RefreshingNeeded then -1 else 0)
; Directive=3: OrbitXY ← argument 1
; Directive=4: OrbitDBCWidth ← argument 1
; Directive=5: OrbitFont ← argument 1
; Directive=6: result ← OrbitDeltaWC
; Directive=7: OrbitInk ← argument 1
; Directive=10b: result ← OrbitDBCWidth
; Directive=11b: OrbitROSCommand ← argument 1
; Directive=12b: Read data words (OrbitData)
;
argument 1 = count of words to read
;
argument 2 = address to put first word
; Directive=13b: Shovel a character to Orbit
;
OrbitHeight ← argument 1
;
OrbitXY ← argument 2
;
OrbitDBCWidth ← nBandsM1
;
for i=0 to abs(LoTable)-1 do OrbitFont←FA!i
;
(use "tasking" loop if LoTable>0, else non-tasking)
;
result ← OrbitDBCWidth
;
NewRp ← OrbitDeltaWC
; Directive=14b: Process an entire page and send to Slot
;
argument 1 = pointer (even) to ROS command table.
;
ROS command table entries are 2 words each:
;
whenflag bit -- 0 means do it at BandM1
;
1 means do it now
;
command bit 3-- which command to do
;
BandM1 bit 12. -- do it when nBandsM1 matches this field
;
rosArgument bit 16. -- this is the argument
;
Commands:
;
0 -- Send rosArgument as a ROS command
;
1 -- spare
;
2 -- spare
;
3 -- Wait (used if 2 ROS commands needed in same band)
;
argument 2 = Timeout count, in number of refresh cycles
;
result ← updated NewRp (remember it’s 1 below next char)
; Directive=15b: Process a single band and return
;
result ← updated NewRp (remember it’s 1 below next char)
; Directive=16b: Read a single word of ROS status (argument 1
;
contains, in the left half, the first address of ROS memory
;
to look in).
;
result ← status word
;
;Orbit microcode
;
;Orbit -- task 1 (just below the emulator)
; PackMu SpruceMc.Mb SpruceMc.Br 177774 (less bits for any other tasks)
;
; Comment conventions:
;
**Put on any instruction after which a TASK switch might happen
;
!a,bBranching between locations a and b may occur
;
[a,b]Same
;
//Put on instructions inserted to make sure Alto clock does not
;
stop during execution of an Orbit function.
;
;
;Orbit definitions
;
$ORBITDWC
$L0, 070014, 100;F1=14 Alto←Delta Word Count
$ORBITDBCWID
$L26010, 70015, 120100;F1=15 Alto←Delta BC, Width (-1)
;
F2=10, Delta Bc, Width←Alto, Cinit
$ORBITDBCWIDx
$L16015, 0, 160000;F1=15 (version that does not define BUS)
$ORBITXY
$L26011, 0, 120000;F2=11, X,Y ← Alto
$ORBITHEIGHT
$L26012, 0, 120000;F2=12, Height ← Alto !!!BRANCHES!!!
$ORBITFONT
$L26013, 0, 120000;F2=13, Font data ← Alto
$ORBITINK
$L26014, 0, 120000;F2=14, Ink data ← Alto
$ORBITCONTROL
$L26015, 0, 120000;F2=15, Control, FA ← Alto
$ORBITROSCMD
$L26016, 0, 120000;F2=16, Ros command ← Alto
$ORBITDATA
$L0, 70016, 100;F1=16, Alto ← Output data
$ORBITSTATUS
$L0, 70017, 100;F1=17, Alto ← Status !!!BRANCHES!!!
$ORBITSTATUSx
$L16017, 0, 160000;F1=17 (version that does not define BUS)

$BUSUNDEF
$L0, 14002, 100;Leaves BS=2 so bus is =-1
;

; Orbit Control bits:
$GOAWAY
$10;
$WHICH
$4;
$CLRFRESH
$2;
$CLRBEHIND
$20;
$SLOTTAKE
$300;Includes "enable" bit
$STABLEROS
$40;
$600
$600;
$400
$400;
$4000
$4000;
$6000
$6000;
$10000
$10000;

;; 27 December, 1977 -- reassign R71-R76 to R46-R53 -- avoids all Tricon conflicts

$DIRECTIVE
$R53;was R76
$ARG1
$R52;
$ARG2
$R51;
$NBANDSM1
$R50;
$FA
$R47;
$LOTABLE
$R46; was R71
$FONTTABLE
$R70;
$NEWRP
$R67;
;; March 6, 1978 no longer used, removed due to TriCon name conflict $STATUS $R66;
$PROGRESULT
$R66; ; 8 March, 1978
$RET0
$R64;
$RET1
$R63;
$LORP
$R62;
$LOWP
$R61;
$ORBBL
$R60;
$XY
$R57;
$BEGFADR
$R56;
$ICC
$R56;
$C720
$R55;
$Shit
$R54;

$LASTL
$R40;Last value of L in RAM

$TEMP
$R17;March 6, 1978 Was R14, switched to avoid TriCon conflict
$FONTADR
$R15;
$HEIGHT
$R16;
;
; ORBIT -- here to load state from the control block, and to
; dispatch on the directive.

; Global dispatch definitions:
!1,2,LOLOOP,NCHAR;
Return from TFRCHR
!1,2,BANDRET0,BANDRET1;
Return from DOBAND
!3,4,REFRET0,REFRET1,REFRET2,REFRET3;
Return from REFRESH
!17,20,DIR0,DIR1,DIR2,DIR3,DIR4,DIR5,DIR6,DIR7,DIR10,DIR11,DIR12,DIR13,DIR14,DIR15,DIR16,DIR17;

!1,2,ORBITX,ORREFA;

ORBIT:
T←16;
L←736-T, TASK;
C720←L;**** Wait here on a block...
MAR←C720;
NOP;available
L←MD, TASK;
ORBBL←L;** ORBBL points to our control block

; Pick up the directive, argument 1
ORBITX: MAR←ORBBL;
L←ORBBL+1;
ORBBL←L;
L←MD;
T←MD;
DIRECTIVE←L, L←T, TASK;
ARG1←L;**

; Pick up argument 2, nBandsM1
MAR←L←ORBBL+1;
L←LASTL+1;
ORBBL←L;
L←MD;
T←MD;
ARG2←L, L←T, TASK;
NBANDSM1←L;**

; Pick up FA, LoTable
MAR←L←ORBBL+1;
L←LASTL+1;
ORBBL←L;
L←MD;
T←MD;
FA←L, L←T, TASK;
LOTABLE←L;**

; Pick up FontTable, NewRp
MAR←L←ORBBL+1;
L←LASTL+1;
ORBBL←L;
L←MD;
T←MD;
FONTTABLE←L, L←T, TASK;
NEWRP←L;**

; Dispatch to appropriate function
T←17;
L←DIRECTIVE AND T;
SINK←LASTL, BUS, TASK;
:DIR0;**

; ORBITDONE/STORE -- here when done with a function. Zero location
; 720b, and idle. Idle is normally BLOCK; but will sit in a loop
; refreshing if high order bit of directive is on.
;
ORBITSTORE -- returns what is in L as result
;
ORBITDONEX -- XOR’s what is in L with status

!1,2,ORQUIET,ORREF;
!4,5,IACS,,,,NOIACS;

ORBITSTORE: PROGRESULT←L;
ORBITDONE:
L←0, TASK;
ORBITDONEX: ICC←L;
**
L←ORBITSTATUS;
T←100000, :IACS;
IACS:
L←LASTL XOR T;
NOIACS: T←ICC;
MAR←ORBBL+1;
L←LASTL XOR T;
MD←PROGRESULT, TASK;
MD←LASTL;**

; Record done, store diagnostic Shit, quit or enter refresh loop
MAR←C720;
L←DIRECTIVE;
MD←0;
MD←Shit;
SH<0, TASK;
:ORQUIET; ** [ORQUIET, ORREF]

; ORQUIET -- let Orbit be quiet between invocations. Turn off
; the RUN flop with BLOCK, and wait for StartIO to get it going
; again. Note that the block actually "takes" at the next TASK,
; just after ORBIT.

ORQUIET: BLOCK, :ORBIT;

; ORREF -- Orbit’s idle loop will refresh if needed. Whenever it wakes
; up and discovers a non-zero command block, it will resume execution.
; Issuing a StartIO at any time will simply hasten the wakeup.

ORREF:
ORBITCONTROL←GOAWAY;
NOP, TASK;
REFRET3: NOP;
**Wait for a good long time (2ms)
MAR←C720;
NOP;
L←MD, BUS=0, TASK;
ORBBL←L, :ORBITX;** !ORBITX,ORREFA

ORREFA:
L←3, TASK, :REFRESH;Return to REFRET3 on new wakeup
;
; Directive 0: Control ← argument 1
DIR0:
ORBITCONTROL←ARG1;
NOP,TASK;
NOP, :ORBITDONE; **-- Let us go away if GOAWAY was set in last instr

; Directive 1: argument ← Orbit data
DIR1:
L←ORBITDATA, :ORBITSTORE;

; Directive 2: Set Height, return -1 if refresh needed
!4,5,NONEEDREF,,,,NEEDREF;

DIR2:
ORBITHEIGHT←ARG1;
L←0, :NONEEDREF;
NONEEDREF: :ORBITSTORE;
NEEDREF: L←ALLONES, :ORBITSTORE;

; Directive 3: Set XY ← argument 1
DIR3:
ORBITXY←ARG1, :ORBITDONE;

; Directive 4: Set delta BC, Width ← argument 1
DIR4:
ORBITDBCWID←ARG1, :ORBITDONE;

; Directive 5: Ship font data ← argument 1
DIR5:
ORBITFONT←ARG1, TASK;
NOP, :ORBITDONE; ** In case FIFO full....

; Directive 6: Read delta WC
DIR6:
L←ORBITDWC, :ORBITSTORE;

; Directive 7: Set ink data ← argument 1
DIR7:
ORBITINK←ARG1, :ORBITDONE;

; Directive 10b: Read delta BC, Width
DIR10:
L←ORBITDBCWID, :ORBITSTORE;

; Directive 11b: ROS command ← argument 1
DIR11:
ORBITROSCMD←ARG1, :ORBITDONE;

; Directive 12b: Read orbitdata words. First argument is count
; Second argument is address


DIR12:
L←ARG2-1, TASK;
TEMP←L;** Temp=beginning core address-1
T←TEMP;
L←ARG1+T, TASK;
ARG1←L;**ARG=last address

; 6 instructions in the loop to allow Orbit memory adequate time.
; Orbit really needs only 4 instructions
; per ORBITDATA function.

!1,2,F12CONT,F12DON;
F12CONT: MAR←L←TEMP+1, T←TEMP;
TEMP←L;
L←ARG1-T;
MD←ORBITDATA;
SH=0, TASK;
:F12CONT; ** [F12CONT,F12DON]

F12DON:
NOP, :ORBITDONE; **

; Directive 13b: Load Height, XY, then DBCWID, shovel
; a number of words at the interface, then read delta WC
;
Argument 1: Height
;
Argument 2: XY
;
NBANDSM1: Width
;
FA: pointer to data vector
;
LOTABLE: count (may be positive or negative -- see below)

!4,1,KILLHEIGHT13;
!1,2,CONTLOP,DONLOP;
!1,2,CONTLOPT,DONLOPT;
!1,2,LOPTA, LOPNA;

DIR13:
ORBITHEIGHT←ARG1;
ORBITXY←ARG2, :KILLHEIGHT13;
KILLHEIGHT13:
ORBITDBCWID←NBANDSM1;
L←T←LOTABLE;
L←FA-1, SH<0;
FA←L, L←T, :LOPTA;!LOPTA,LOPNA

; Two versions of this loop. First one does not task, so logic
; analyzer can be used on small loops.
; Second one tasks so can be used on large characters.
; Count<0 selects non-tasking loop.

CONTLOP: FA←L;
L←LOTABLE+1;
NOP;///////////////////////;
ORBITFONT←MD;
LOPNA: LOTABLE←L, SH=0;
MAR←L←FA+1, :CONTLOP;**DONT DO A TASK**

CONTLOPT: MAR←L←FA+1;
FA←L;
L←LOTABLE-1;
NOP;///////////////////////
ORBITFONT←MD;
LOPTA:
LOTABLE←L, SH=0, TASK;
NOP, :CONTLOPT;**DO A TASK**


!1,2,WAITLOP,WAITDONE;
DONLOPT: L←100, :WAITLOP0;
DONLOP: L←100;
WAITLOP0: TEMP←L, :WAITLOP;
**
WAITLOP: L←TEMP-1, BUS=0, TASK, :WAITLOP0;

; The following is a non-standard way of storing a result
; (it comes back in the word of the control table occupied by
; NewRp)
WAITDONE: MAR←ORBBL;
NOP, TASK;
MD←ORBITDWC;**
L←ORBITDBCWID, :ORBITSTORE;

; Directive 15b: Do one band

DIR15:
L←0+1, TASK, :DOBAND;
BANDRET1: :ORBITDONE;

; Directive 16b: Read one word of ROS Status

!1,2,WDSTLP,WDSTDN;
!1,2,MSH1,MSH2;
!1,2,MSHGOOD,MSHBAD;
!4,1,MSHKILL;
!4,1,MSHKILL1;
!4,1,MSHKILL2;

DIR16:
L←ORBITSTATUS;
FA←L, :MSHKILL1;Remember StableROS bit
MSHKILL1: L←3, TASK, :MSH3;

WDSTLP:
L←3, :MSH0;
MSH1:
L←TEMP, TASK;
TEMP ← L LSH 1;**
L←ICC-1, BUS=0;
MSH0:
ICC←L, :MSH1;
MSH2:
T←400;
L←ORBITCONTROL←ARG1+T;L←ARG1+T, ORBITCONTROL←ARG1
ARG1←L;
T←17;
T←ORBITSTATUS.T;Branches
L←TEMP + T, TASK, :MSHKILL;
MSHKILL: TEMP←L;
**
L←XY-1, BUS=0, TASK;
MSH3:
XY←L, :WDSTLP;**

WDSTDN:
T←FA;
T←ORBITSTATUS.T;
L←STABLEROS AND T, :MSHKILL2;
MSHKILL2:
L←TEMP, SH=0;
PROGRESULT←L, :MSHGOOD;
MSHGOOD:
:ORBITDONE;
MSHBAD:
T←20000, :ORBITDONEX;
;
; Directive = 17b: Spare
;
DIR17:
:ORBITDONE;
;
; Slot Printing loop (directive=14b)
; Register values on entering:
;
FA -- first read address in band
;
NBANDSM1 -- NumberOfBands-1
;
ARG1 -- pointer to ROS command table of pairs (x, cmd)
;
where x=(i,op,b) i=bit0, op=bits1-3, b=bits4-15 and
;
i=0 if op is to be done when NBANDSM1=b
;
1 if op is to be done immediately
;
op=0 if cmd is to be sent to ROS, 1 if status is to be read
;
and 3 to wait
;
b=band number (first one to be executed is NBANDSM1,
;
and so on decreasing to 0).
;
ARG2 -- timeout count down
;
+ see subrs
; Uses: RET0
; Calls: REFRESH, DOBAND

!4,1,NXROS;
Make sure NXROS will kill ORBITSTATUS branch
!1,2,SVBND,DIR14DN;
!1,2,IMMEDIATE,CHECKBAND;
!1,2,NOROS,GIVEROS;
!1,2,NOTIMEOUT,TIMEOUT;
!4,5,NXBAND,,,,REFRSH2;

DIR14:
ORBITCONTROL←SLOTTAKE;
T←WHICH;Set FA properly.
L←FA+T, TASK;
ORBITCONTROL←LASTL; **
L←NBANDSM1+1;
PROGRESULT←L;Would never otherwise be set to this value

; Ship out ROS commands in the command table.

NXROS:
MAR←ARG1;Look for ROS command
T←NBANDSM1;
T←40000 OR T;
T←30000 OR T;
L←MD-T; L will be negative only if MD is positive
T←7777;
L←LASTL AND T, SH<0;
:IMMEDIATE, SH=0, TASK; !IMMEDIATE,CHECKBAND
CHECKBAND: :NOROS;
** !NOROS,GIVEROS
IMMEDIATE: :GIVEROS; **

NOROS:
L←0, TASK, :DOBAND;Go do most of the work.

; Return from band processing

BANDRET0: ORBITCONTROL←GOAWAY;
L←ARG2, TASK;
ICC←L;**Wait a long time here (2 ms)

; Quit early if BEHIND and SendVideo is gone, store Orbit status every band

!1,2, SGOAWAY, PGABORT;
!4,1, BRSTATKILL;
!5,2, BRHOLDKILL, BRHOLDSTORE;

REFRET2: ORBITCONTROL←0
;Read SendVideo
T←2;Store status
MAR←ORBBL+T;
L←ORBITSTATUS;Branches!
MD←LASTL, :BRSTATKILL; !BRSTATKILL, BRSTATKILL
BRSTATKILL: T←30;
10-7-77 DCS !!!
L←LASTL AND T;
T←20;
L←LASTL-T;10-3-77 DCS
SH=0, TASK;Quit if behind and SendVideo gone
:SGOAWAY;! SGOAWAY, PGABORT **
PGABORT: L←10000, TASK, :ORBITDONEX; Quit

; Save band number whenever word 8, bit 3 of status is on (Dover Count-H)

SGOAWAY: ORBITCONTROL←20000;Read word 8, first nybble [0-3] of status
NOP;//////Must wait two cycles before getting results
L←0+1;;For ANDing with ORBITSTATUS on next cycle
ORBITSTATUSx, SINK←LASTL, BUS; Branches! (Next[7] due to hardware, Next[9] if count-H)
L←NBANDSM1, :BRHOLDKILL; !BRHOLDKILL, BRHOLDSTORE; which band if count-H on
BRHOLDSTORE: PROGRESULT←L;
BRHOLDKILL: ORBITHEIGHT←0; Branches!! check to see if refresh needed
:NXBAND;!NXBAND,REFRSH2

REFRSH2: L←ICC-1, BUS=0;
ICC←L, :NOTIMEOUT;!NOTIMEOUT,TIMEOUT
NOTIMEOUT: L←2, TASK, :REFRESH;
Return to REFRET2 on new wakeup

; Time to begin generating a new band.

NXBAND: L←NBANDSM1-1, BUS=0, TASK;
NBANDSM1←L, :SVBND;**
SVBND:
T←4;
MAR←ORBBL-T;Update the command block to show progress
TASK;
MD←NBANDSM1, :NXROS;**

TIMEOUT: L←40000, TASK, :ORBITDONEX;
DIR14DN: :ORBITDONE;
;
; Dispatch on ROS command table entry (high 4 bits)

%360,360,0,ROS0,ROS1,ROS2,ROS3;

GIVEROS: MAR←ARG1;
T←2;
L←ARG1+T;
ARG1←L;
T←30000;
L←MD AND T;
TEMP← L LCY 8;
L←MD, TASK;
RET0←L;**
SINK←TEMP, BUS, TASK;
:ROS0;

; Op code 0: send a 16-bit ROS command
ROS0:
ORBITROSCMD←RET0, :NXROS;

; Op code 1: read status
ROS1:
ORBITCONTROL←RET0;
MAR←ARG1-1;
NOP;
MD←ORBITSTATUS;Warning--may or 4 into NEXT
:NXROS;

; Op code 2: spare
ROS2:
:NXROS;

; Op code 3: wait in a loop -- argument tells how long.
ROS3:
NOP;
!1,2,ROS3A,ROS3B;
ROS3A:
L←RET0-1, BUS=0, TASK;
RET0←L, :ROS3A;**
ROS3B:
:NXROS;
;
;DOBAND -- enter here to process a band.
;
L = index of return (BANDRET0,BANDRET1)
;
NEWRP => next new character -1
;
LOTABLE => left-over table (@LOTABLE=0 at the very first)
;
FONTTABLE => ICC table (-#100000)
; Uses RET1,LORP,LOWP,FONTADR,HEIGHT,XY,ICC
; Calls REFRESH, TFRCHR

DOBAND:
RET1←L;**
L←LOTABLE-1;
LORP←L, TASK;
LOWP←L;**

; Process left-overs
!4,5,NOREFRSH0,,,,REFRSH0;
!1,2,LOLOOPA,NOLOV;

LOLOOP:
MAR←L←LORP+1;
L←LASTL+1;
LORP←L;
NOP;///////////////////////
L←ORBITHEIGHT←MD;ORBITHEIGHT branches!!
HEIGHT←L, SH=0, :NOREFRSH0;
NOREFRSH0: L←ORBITXY←MD, TASK, :LOLOOPA;

LOLOOPA: XY←L;
**
MAR←L←LORP+1;
L←LASTL+1;
LORP←L;
NOP;///////////////////////
ORBITDBCWID←MD;
L←MD;
FONTADR←L, L←0, TASK, :TFRCHR;L=0 => return to LOLOOP

; Come to REFRSH0 to refresh when in the left-over
; loop. Backs up the LORP pointer and returns to LOLOOP.
!1,1,REFRSH0A;
Kill SH=0 coming from above
REFRSH0: T←2, :REFRSH0A;
REFRSH0A: L←LORP-T, TASK;
Back up the read pointer
LORP←L;**
L←0, TASK, :REFRESH;
REFRET0: :LOLOOP;

; Come to NCHAR when finished with left-over table (terminating
; 0 encountered).

; Process "new characters" from the main list.

!4,5,NOREFRSH1,,,,REFRSH1;
!1,2,NOTCHAR,REGCHAR;
!1,2,DOBR, NOBR;
; Band command dispatch, for all but characters
!37,40, ENDBAND, REGRULE, TRP2, TRP3, BRANCH, TRP5, TRP6, TRP7;

NOBR:
NOP, :NCHAR; **Branch command did not perform a "branch"
NOLOV:
NOP;**
NCHAR:
MAR←L←NEWRP+1;
L←LASTL+1;
NEWRP←L;
L←T←MD;T←cmd, L←cmd for test
L←MD, SH<0;L←XY
XY←L, :NOTCHAR;to REGCHAR if char

REGCHAR: MAR←FONTTABLE+T;
ORBITXY ← XY;
NOP;
L←MD+1, TASK;
FONTADR←L;**
MAR←FONTADR-1;
L←FONTADR+1;
NOP;///////////////////////
GETHW:
FONTADR←L;
ORBITHEIGHT←L←MD;Branches on NEXT[7] !!
HEIGHT←L, L←0+1, :NOREFRSH1;

NOREFRSH1: ORBITDBCWID←MD, TASK, :TFRCHR;
L=1 => return to NCHAR

!4,1,KILLHEIGHT0;

REFRSH1: L←MD, TASK;
ICC←L;** Save DBCWID
L←0+1, :REFRESH;
REFRET1: ORBITHEIGHT←HEIGHT;
Branches!!
ORBITXY←XY, :KILLHEIGHT0;
KILLHEIGHT0: ORBITDBCWID←ICC;
L←0+1, TASK, :TFRCHR;

; If not a character, dispatch

; T = cmd, XY = cmd word 2
NOTCHAR: L←7 AND T;
SINK ← LASTL, L←T, BUS, TASK;Dispatch on cmd[11-15]
ICC ← L, :ENDBAND;** ICC ← cmd ! ENDBAND, REGRULE, , , BRANCH,...

; We have an "end band" signal in the new character list.

ENDBAND: MAR←LOWP+1;
Terminate the left over list
SINK←RET1, BUS, TASK;
MD←0, :BANDRET0;

; Do a rule.
REGRULE: MAR←L←NEWRP+1;
L←LASTL+1;
NEWRP←L;
ORBITXY ← XY;
L←0, :GETHW;

; If <function table>!10 ne cmd, "branch" to <current band loc> + cmd word 2

BRANCH: T←3;
MAR←ORBBL+T;function table!10
T←ICC;command word
L←MD-T;
T←XY, SH=0;T←"branch" increment
L←NEWRP+T, TASK, :DOBR;"branch" if not equal ! DOBR, NOBR

DOBR: NEWRP ← L, :NOLOV; **
implement the "branch"

; Catch illegal band entries, or microprocessor problems

TRP2: L←NEWRP, :BANDTRAP;
TRP3: L←NEWRP, :BANDTRAP;
TRP5: L←NEWRP, :BANDTRAP;
TRP6: L←NEWRP, :BANDTRAP;
TRP7: L←NEWRP, :BANDTRAP;

; 721 ← band entry address
; Return with firmware status #4000

BANDTRAP: Shit←L;
L←4000, :ORBITDONEX;
;
; TFRCHR -- Transfer a character part to the Orbit.
;
; Register values on entering (*** means already passed to Orbit):
;
L -- "return" address (0=>LOLOOP; 1=>NCHAR)
;
XY -- xy position in Orbit format (ORBITXY) ***
;
HEIGHT -- height in Orbit format (ORBITHEIGHT) ***
;
FONTADR -- pointer to first data word of the font character
;
If FONTADR=0, it will be a "rule" instead
;
(bc,width) -- has already been given to Orbit (ORBITDBCWID←) ***
;
LOWP -- write pointer into left overs
; Uses RET0, BEGFADR
;
!7,10,FONTODD,FONTEVEN,,,FONTDONE,,,;
!1,2,FONTLA,FONTRULE;
!1,2,FONTLO,FONTDN;
!4,5,FONTRULEC,,,,FONTRULED;

TFRCHR:
RET0←L;**Save return address
MAR←T←FONTADR, BUS=0;
L←ONE AND T, :FONTLA;Check to see if first address odd or even
FONTLA:
L←FONTADR+1, SH=0;
BEGFADR←L, :FONTODD;

FONTLP:
MAR←L←FONTADR+1;
NOP;///////////////////////
L←LASTL+1;
FONTEVEN: ORBITSTATUSx, FONTADR←L;
Branches!! check to see if done
ORBITFONT←MD, TASK, :FONTODD;
FONTODD: ORBITFONT←MD, :FONTLP;
**

; Come here to put out a "rule" -- just give Orbit all -1’s
; as font bits.
FONTRULE: ORBITSTATUSx;
Check to see if finished
ORBITFONT←BUSUNDEF, TASK, :FONTRULEC;
FONTRULEC: ORBITFONT←BUSUNDEF, :FONTRULE;
**

; Now undo the effect on bumping the Font Address

FONTRULED: NOP;**
T←ORBITDWC;
L←ONE-T, TASK;
BEGFADR←L, :FONTDNX;**

FONTDONE: NOP;
**
FONTDNX: T←7777, ORBITDBCWIDx;
Read remaining width
L←7777-T;
T←ORBITDWC-1;
L←BEGFADR+T, SH=0, TASK;
FONTADR←L, :FONTLO;**

; Left over to record. Format:
;
word 0: height
;
word 1: y (x=0)
;
word 2: dbc,width
;
word 3: font address

FONTLO: T←7777;
L←XY AND T, TASK;
BEGFADR←L;**

MAR←L←LOWP+1;
L←LASTL+1;
MD←HEIGHT;
MD←BEGFADR, TASK;
LOWP←L;**

MAR←L←LOWP+1;
L←LASTL+1;
MD←ORBITDBCWID;
MD←FONTADR, TASK;
LOWP←L;**

FONTDN:
SINK←RET0, BUS, TASK;
:LOLOOP;**
;
; REFRESH -- the place that all refreshing is done (for now)
; Requires about 35*3+7 = 112 microcycles
; Register values on entering:
;
L -- return index
; Uses RET0, TEMP(R) -- but doesn’t change it

; Note that a good deal of Orbit state is destroyed.
; Calculation of number of times through loop:
;
let n=number to store in L at beginning. (n+1)*2=64.+6.
;
6 is to leave enough in the FIFO.

!4,5,REFLPA,,,,REFLPD;
!4,1,REFLP;
Kill height branch

REFRESH: RET0←L;
**
ORBITXY←0;
ORBITHEIGHT←6000;Branches!! 1024. bits = 64. words
ORBITDBCWID←0, :REFLP;
REFLP:
L←TEMP, ORBITSTATUSx;Branches!! check to see if done.
ORBITFONT←0, TEMP←L, TASK, :REFLPA; TEMP←L just to hold BUS=0
REFLPA:
ORBITFONT←0, :REFLP;**

; Note about the exit code. If GOAWAY is set, the REFRESH subroutine
; does not return until a new wakeup is generated (either by
; another refresh request or by someone clearing GOAWAY: StartIO
; or buffer-switch).

REFLPD:
ORBITCONTROL←CLRFRESH;**
SINK←RET0, BUS, TASK;
:REFRET0;**Usually hangs up here if no wakeup

; Excerpts from version created in 4-78 for Alto II XMs, assuming memory data available
;; only in instructions 5 and 6 of a memory cycle
;GIVEROS: MAR←ARG1;
;
T←2;
;
L←ARG1+T;
;
ARG1←L;
;
T←MD;
;
L←MD;
;
RET0←L;
;
L←30000 AND T, TASK;
;
TEMP←L LCY 8; **
;
SINK←TEMP, BUS, TASK;
;
:ROS0; [ ROS0, ROS1, ROS2, ROS3 ]

;
L←ORBITHEIGHT←MD;ORBITHEIGHT branches!!
;
T←ORBITXY←MD, :NOREFRSH0; [ NOREFRSH0, REFRSH0 ]
;NOREFRSH0:
;
HEIGHT←L, L←T, SH=0, TASK; ~~ WOW!
;
XY←L, :LOLOOPA; ** [ LOLOOPA, NOLOV ]
;LOLOOPA:
;
MAR←L←LORP+1;
;
L←LASTL+1;
;
LORP←L;
;
NOP;///////////////////////
;
ORBITDBCWID←MD;
;
L←MD;
;
FONTADR←L, L←0, TASK, :TFRCHR;L=0 => return to LOLOOP
;; Come to REFRSH0 to refresh when in the left-over
;; loop. Backs up the LORP pointer and returns to LOLOOP.
;REFRSH0: T←2, :REFRSH0A;
;REFRSH0A: L←LORP-T, TASK;
Back up the read pointer
;
LORP←L;**

;NOLOV:
MAR←L←NEWRP+1, :NCHAR1 ; ~~ XM: End of LO List -- avoid too-long chain
;NCHAR:
MAR←L←NEWRP+1;
;NCHAR1:
L←LASTL+1;
;
NEWRP←L;
;
L←T←MD;T←cmd, L←cmd for test
;
L←MD, SH<0;L←XY (don’t TASK here! T is in use!)
;
XY←L, :NOTCHAR; [ NOTCHAR, REGCHAR ]
;REGCHAR: MAR←FONTTABLE+T;
;
ORBITXY ← XY;
;
L←MD+1;
;
MAR←LASTL-1;
;
L←LASTL+1;
;
NOP;////////////////////////
;GETHW:
;
FONTADR←L;
;
ORBITHEIGHT←L←MD;Branches on NEXT[7] !!
;
T←MD, :NOREFRSH1; [ NOREFRSH1, REFRSH1 ]
;NOREFRSH1:
;
HEIGHT←L, L←T, TASK; XM: Timing is very tight. Next instr. is 20th cycle without TASK
;
ORBITDBCWID ← LASTL; **
;
L←0+1, TASK, :TFRCHR;
;!4,1,KILLHEIGHT0;
;REFRSH1: HEIGHT←L, L←T, TASK;
;
ICC←L;** Save DBCWID
;
L←0+1, :REFRESH;

;REGRULE:
;
ORBITXY ← XY;
;
L←NEWRP+1;
;
L←LASTL+1;
;
MAR←LASTL-1; Carefully placed with respect to double word fetch at GETHW
;
NEWRP←L;
;
L←0, :GETHW;

;!4,5,FONTODD,,,,FONTDONE;
;!1,2,FONTLA,FONTRULE;
;!1,2,FIRSTODD, FONTEVEN;
;!1,2,FONTLO,FONTDN;
;!4,5,FONTRULEC,,,,FONTRULED;
;TFRCHR:
;
RET0←L;**Save return address
;
T←FONTADR, BUS=0;
;
L←ONE AND T, :FONTLA;Check to see if first address odd or even
;FONTLA:
;
MAR←T;Carefully placed with respect to double word fetch at FONTEVEN
;
L←FONTADR+1, SH=0;
;
BEGFADR←L, :FIRSTODD; [ FIRSTODD, FONTEVEN ]
;FIRSTODD: NOP, :FONTODD; /////////////// Dammit! ///////////////
;FONTLP:
;
MAR←L←FONTADR+1;
;
NOP;///////////////////////
;
L←LASTL+1;
;FONTEVEN:
;
ORBITSTATUSx, FONTADR←L;Branches!! check to see if done
;
ORBITFONT←MD, TASK, :FONTODD;
;FONTODD: ORBITFONT←MD, :FONTLP;
**
;

;; DCS, September 24, 1977 4:56 PM, add Behind-abort, BRANCH band command
;; October 3, 1977 9:33 PM, repair behind-abort (wrong test, wrong status bit)
;; October 6, 1977 5:04 PM, per RFS suggestion, move behind-abort test to rfrsh loop
;; October 7, 1977 11:59 PM, SendVideo is 10, not 4!!!!! (behind-abort)
;; October 16, 1977 3:57 PM, Add bad band code traps, 4000 firmware bit
;; December 27, 1977 2:21 PM, Reassign R71-R76 to get out of Tricon’s way
;; March 6, 1978 4:35 PM, revived as component fetched from SpruceMc.Mu
;; (had been copied in for a while)
;; March 8, 1978 8:56 AM, Left out dispatch constraint specs in latest reorganization
;; March 8, 1978 4:58 PM, store last band in which Count-H (Dover word 8, bit 3) was
;;
seen in command table result word to Program Result (FUNC!8)
;; March 16, 1978 12:06 AM, was TASKing instead of TISKing, causing random branch
;;
into display task -- oh, ugh!
;; March 26, 1978 10:11 PM, count-H fix -- wait two cycles (one necessary, one sometimes)
;; May 9, 1978 9:28 AM, add XM fix comments
;; October 17, 1978 2:46 PM, add immediate command-forwarding to fslot. BWB
;; October 17, 1978 4:51 PM, bum some code (remove high order trap vector, bum a few)
;;