; O R B I T Microcode ; ; Must be fetched from a root microcode file that defines the low-RAM locations, etc. ; ; 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 "page jump" (2 words). First word is PN (low order ; 5 bits of PN must be 4b). Second word is WC. ; If PN ne CurrentCopy (10th control table entry, below), ; WC words in the "new charcter" list will be passed up. ; (d) 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 ;10. CurrentCopy -- used to jump around some band entries ; that do not apply for this page. (See NewRp, above) ; ; 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,b Branching 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; $170000 $170000; ;; 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) ;;