; 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:
;0Directive -- tells which function to execute
;1Argument 1 -- first argument to the function
;2Argument 2 -- second argument
;
; ...entries below here used only for directive 12 and 13 ...
;3nBandsM1 -- number of bands (-1) to generate
;A band is 16. scan-lines
;4FA -- first read address for output (left half-word)
;5LoTable -- pointer to left-over table
;Must be even; must be initialized with @LoTable=0
;6FontTable -- 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
;7NewRp -- 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:
;command bit 4-- 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=(op,b) op=bits0-3, b=bits4-15 and
; 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,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;
L←MD-T; L will be negative only if MD is positive
T←7777;
L←LASTL AND T;
SH=0, TASK;
:NOROS;** !NOROS,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;**
XMAR←FONTADR-1;April 5, 1979, Get fonts from alternate bank
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
SINK←FONTADR, BUS=0;April 5, 1979, Uses F2, which is also used to do XMAR
XMAR←T←FONTADR, :FONTLA;April 5, 1979, get font data from alternate bank
FONTLA:
L←ONE AND T;
L←FONTADR+1, SH=0;
BEGFADR←L, :FONTODD;
FONTLP: XMAR←L←FONTADR+1;April 5, 1979, get font data from alternate bank
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). DCS
;; April 5, 1979 9:14 AM, obtain font width, height, raster data from bank indicated by Orbit’s
;;alternate XM bank register.
;; April 8, 1979 1:35 PM, repair bug in XM code yielding random even-odd test results
;;