{File name : PixelBlt.mc Author : Gwan Santosa & Don Charnley Date : 17-Apr-85 15:31:21 Original design by : Don Charnley Date : 18-Mar-85 11:58:22 combine the source and dest pixel-maps together using the Combine Array as follows: It is page alligned! The Combine Array is 256 entries of 4 nibl's each It is addressed by the source nibl value concatenated with the dest nibl value the dest nibl is replaced with the following nibl: (dstX even, dstY even) ← entry[0] (dstX odd, dstY even) ← entry[1] (dstX even, dstY odd) ← entry[2] (dstX odd, dstY odd) ← entry[3] This allows texturing, which increases the effective number of "colors" beyond 16. called with the following parameters: S-16 Combine Array: {pointer - page alligned!!} S-14 Source BitMap: {BitMap} S-12 Source X: {of "transfer area" upper left pixel} S-10 Source Y: {of "transfer area" upper left pixel} S-8 Dest BitMap: {BitMap} S-6 Dest X: {of "transfer area" upper left pixel} S-4 Dest Y: {of "transfer area" upper left pixel} S-2 Transfer width: {smallp - pixels} S-0 Untransfered width: {smallp - pixels / 0 on initial call} tos Transfer height: {smallp - lines} "BitMap" is a six word record of the following format: 0: BitMapBaseHi -- High word of Virtual Addr of [X = 0, Y = Height - 1] of BitMap {upper left screen corner} 1: BitMapBaseLo -- Low word of Virtual Addr of [X = 0, Y = Height - 1] of BitMap {upper left screen corner} 2: BitMapRasterWidth {words} 3: BitMapHeight {lines} 4: BitMapWidth {bits} 5: BitMapBitsPerPixel {1 or 4 or 8} 4 = nibl inner loop looks like the following: for each dest nibl: get next source nibl{4 bits} get next dest nibl{4 bits} Vals ← CombineArray[srcnibl,,dstnibl]{16 bits} newDstNibl ← Vals[2*(dstY mod 2) + (dstX mod 2)]{4 bits} replace dest nibl with newDstNibl registers and links Srclink -- {0, 1, 2, 3} which src nibl, used to know when to refill Dstlink -- {0, 1, 2, 3} which dst nibl, used to know when to refill Loclink -- {0, 1, 2, 3} which nibl of entry desired Share Dstlink and Loclink using three bits [dY mod 2, which dst nibl] SrcReg -- holds unprocessed src nibls DstReg -- holds partially processed dst nibls {old and new} DN -- temp dst nibl for lookup {=Q, in the inner loop} rSAddr -- address of current src word rDAddr -- address of current dst word rArray -- real address of array entry -- temp for array index and value {=Rx, in the inner loop} pixelcount -- number of pixels remaining Perform the operation from the bottom up, so that only the number of lines and tos-1 need to be updated in case of page fault or interrupt if page fault from within a line, save pixel count in tos-1 initialize: read stack parameters save regs calculate links: src start nibl, dst start nibl, (dst Y mod 2) calculate number of dest pixels LINE: fetch first dest word, and allign in DstReg fetch first source word and allign in SrcReg enter loop loop till line finished write last dest word refill: update number of lines remaining, exit if done test for interrupts update src and dest virtual addresses reload src start nibl, dst start nibl, (dst Y mod 2) GOTO[LINE] } Set[L2NBRET1, 02]; Set[L2NBRET2, 04]; Set[L0.PX.NR.0A, 0A]; Set[L0.PX.NR.04, 04]; Set[L0.PX.NR.05, 05]; Set[L0.PX.NR.06, 06]; Set[L0.PX.NR.07, 07]; Set[L0NB3, 0B]; Set[L0NB4, 0C]; Set[L0NB5, 0D]; Set[L1.PX.NR.0A, 0A]; Set[L1.PX.NR.04, 04]; Set[L1.PX.NR.05, 05]; Set[L1.PX.NR.06, 06]; Set[L1.PX.NR.07, 07]; Set[L1SAVE, 9]; RegDef[SrcReg, R, 3]; {=PV} RegDef[DstReg, R, 5]; {=PC} RegDef[rSAddr, R, 0]; {=TOS} RegDef[rhSAddr, RH, 0]; {=rhTOS} RegDef[rDAddr, R, 1]; {=TOSH} RegDef[rhDAddr, RH, 1]; {=rhTOSH} RegDef[rArray, R, 4]; {=S} RegDef[rhArray, RH, 4]; {=rhS} RegDef[urSAddr, U, 38]; {tmp, used in PixelBlt} RegDef[urhSAddr, U, 41]; {tmp, used in PixelBlt} RegDef[urDAddr, U, 43]; {tmp, used in PixelBlt} RegDef[urhDAddr, U, 19]; {tmp, used in PixelBlt} RegDef[upixelcount, U, 45]; {tmp, used in PixelBlt} RegDef[uXoffset, U, 46]; {tmp, used in PixelBlt} {RegDef[uSrcflag, U, 47]; {tmp, used in PixelBlt} RegDef[uDstflag, U, 0C]; {tmp, used in PixelBlt}} RegDef[uSrcBITMAPLo, U, 5D]; {tmp, used in PixelBlt} RegDef[uSrcBITMAPHi, U, 19]; {tmp, used in PixelBlt} RegDef[uSrcXLo, U,57]; {tmp, used in PixelBlt} RegDef[uSrcYLo, U,05]; {tmp, used in PixelBlt} RegDef[uDstBITMAPHi, U, 35]; {tmp, used in PixelBlt} RegDef[uDstBITMAPLo, U, 04]; {tmp, used in PixelBlt} RegDef[uDstXLo, U, 26]; {tmp, used in PixelBlt} RegDef[uDstYLo, U, 31]; {tmp, used in PixelBlt} RegDef[uTrnWidthLo, U, 3A]; {tmp, used in PixelBlt} RegDef[uUnTrnWidthLo, U, 5C]; {tmp, used in PixelBlt} RegDef[uTrnHeightLo, U, 0D]; {= uTOS, used in PixelBlt} { ============================================================================================== Fetch stack parameters ============================================================================================== @PIXELOP: opcode[305'b], Bank ← PIXELBank, c1; This section is stored in PixelBltB1.mc uTOS ← TOS, c2; uTOSH ← TOSH, CROSS[PIXEL], c3; at[PIXEL], Xbus ← ibNA, XDisp, c1; This section is stored in PixelBltB2.mc DISP4[PIXELDISP], c2; } uS ← S, c3, at[00, 10, PIXELDISP]; NNBOP: MAR ← [rhS, S - 1], c1; {Point to UnTrnWidthHi} Ybus ← TOSH xor smallpl, CANCELBR[$, 2], ZeroBr, c2; {Check if transfer height not NIL} Q ← MD, BRANCH[NBTE3, $], c3; MAR ← [rhS, S + 0], c1; {Point to UnTrnWidthLo} S ← S - 2, L1 ← L1.NoFixesB2, c2; TT ← MD, c3; MAR ← [rhS, S -1], c1; {Point to TrnWidthHi} Ybus ← Q xor smallpl, CANCELBR[$, 2], ZeroBr, c2; {Check if UnTrnWidth not NIL} Q ← MD, BRANCH[NBTE1, $], c3; MAR ← [rhS, S + 0], c1; {Point to TrnWidthLo} S ← S - 2, c2; Rx ← MD, c3; Ybus ← Q xor smallpl, ZeroBr, c1; {Check if transfer width not NIL} uUnTrnWidthLo ← TT, ZeroBr, BRANCH[NBTE2, $], c2; uTrnWidthLo ← Rx, ZeroBr, BRANCH[WNZ, WZ], c3; {Check TrnWidth} WZ: BRANCH[GOTR1, NOTR1], c1; {In between lines case} GOTR1: upixelcount ← Rx, c2; {Load number of pixel per line} uXoffset ← 0, GOTO[NFM], c3; {X offset = 0} WNZ: upixelcount ← TT, BRANCH[GOTR2, NOTR2], c1; {Load number of pixel left} GOTR2: Rx ← Rx - TT, CarryBr, c2; {Calculate X offset} uXoffset ← Rx, BRANCH[NOTR4, $], c3; NFM: MAR ← [rhS, S -1], c1; {Point to DstYHi} uTrnHeightLo ← TOS, CANCELBR[$, 2], ZeroBr, c2; {Check if transfer height is 0} Q ← MD, BRANCH[$, NOTR3], c3; MAR ← [rhS, S + 0], c1; {Point to DstYLo} S ← S - 2, L3 ← 1, c2; Rx ← MD, c3; MAR ← [rhS, S -1], c1; {Point to DstXHi} Ybus ← Q xor smallpl, CANCELBR[$, 2], ZeroBr, c2; {Check if Dst Y not NIL} Q ← MD, BRANCH[NBYE1, $], c3; MAR ← [rhS, S + 0], c1; {Point to DstXLo} Ybus ← Q xor smallpl, CANCELBR[$, 2], ZeroBr, c2; {Check if Dst X not NIL} TT ← MD, BRANCH[NBXE1, $], c3; L2 ← L2NBRET1, c1; S ← S - 2, c2; uDstXLo ← TT, c3; MAR ← [rhS, S -1], c1; {Point to DstBITMAPHi} uDstYLo ← Rx, CANCELBR[$, 2], c2; Rx ← MD, c3; MAR ← [rhS, S + 0], c1; {Point to DstBITMAPLo} S ← S + 8, c2; TT ← MD, CALL[GetandTestBitMapParams], c3; S ← S - 10'd, c3, at[L2NBRET1, 10, GetBitMapParamsRet]; PXBK1: MAR ← [rhS, S -1], c1; {Point to SrcYHi} Ybus ← Q xor 4, CANCELBR[$, 2], ZeroBr, c2; {Check if 4 bits per pixel bitmap} Q ← MD, BRANCH[NBPXE1, $], c3; MAR ← [rhS, S + 0], c1; {Point to SrcYLo} S ← S - 2, L1 ← L1.NoFixesB2, c2; TT ← MD, c3; MAR ← [rhS, S -1], c1; {Point to SrcXHi} Ybus ← Q xor smallpl, CANCELBR[$, 2], ZeroBr, c2; {Check if Src Y not NIL} Q ← MD, BRANCH[NBYE2, $], c3; MAR ← [rhS, S + 0], L3 ← 0, c1; {Point to SrcXLo} Ybus ← Q xor smallpl, CANCELBR[$, 2], ZeroBr, c2; {Check if Src X not NIL} Rx ← MD, BRANCH[NBXE2, $], c3; S ← S - 2, c1; uSrcXLo ← Rx, c2; uSrcYLo ← TT, c3; MAR ← [rhS, S -1], c1; {Point to SrcBITMAPHi} CANCELBR[$, 2], c2; Rx ← MD, c3; MAR ← [rhS, S + 0], L2 ← L2NBRET2, c1; {Point to SrcBITMAPLo} S ← S + 14'd, c2; TT ← MD, CALL[GetandTestBitMapParams], c3; S ← S - 16'd, c3, at[L2NBRET2, 10, GetBitMapParamsRet]; PXBK2: MAR ← [rhS, S -1], c1; {Point to CmbARRAYHi} Ybus ← Q xor 4, CANCELBR[$, 2], ZeroBr, c2; {Check if 4 bits per pixel bitmap} Q ← MD, BRANCH[NBPXE2, $], c3; MAR ← [rhS, S + 0], c1; {Point to CmbARRAYLo} rhTT ← Q LRot0, c2; {Set up high VA of color table} TT ← MD, c3; {Set up low VA of color table} Map ← [rhTT, TT + 0], L1 ← L1.NoFixesB2, c1; S ← S + 16'd, L0 ← L0NB5, c2; rhRx ← Rx ← MD, XRefBr, c3; PXBK4: BRANCH[NBCH3, $], c1, at[L0NB5, 10, RMapFixCallerB2]; Q ← uBITMAPHEIGHT, L1 ← L1SAVE, c2; {Save registers} rhArray ← Rx LRot0, CALL[SaveAllRegsB2], c3; {Load the real address of color table} { ============================================================================================== Check boundaries ============================================================================================== } PXBK3: rArray ← Rx, c1, at[L1SAVE, 10, SaveRegsB2Ret]; TT ← uSrcYLo, c2; {Check 1st Y of Src} Ybus ← Q - TT - 1, CarryBr, c3; PXBKE: TT ← TOS + TT, BRANCH[NBE1, $], c1; {TOS = TrnHeight} Ybus ← Q - TT, CarryBr, c2; {Check 2nd Y of Src} TT ← uDstYLo, BRANCH[NBE2, $], c3; {Load Y Dst} Q ← uDBitMapHeight, c1; Ybus ← Q - TT - 1, CarryBr, c2; {Check 1st Y of Dst} TT ← TOS + TT, BRANCH[NBE3, $], c3; Ybus ← Q - TT, CarryBr, c1; {Check 2nd Y of Dst} Q ← uSrcXLo, BRANCH[NBE4, $], c2; {Load X Src} TT ← RShift1 uBITMAPWIDTH, SE ← 0, c3; {Divide Src Bitmapwidth by 4} TT ← RShift1 TT, SE ← 0, c1; Ybus ← TT - Q - 1, CarryBr, c2; {Check 1st X of Src} Rx ← uTrnWidthLo, BRANCH[NBE5, $], c3; Q ← Q + Rx, c1; Ybus ← TT - Q, CarryBr, c2; {Check 2nd X of Src} TT ← RShift1 uDBitMapWidth, SE ← 0, BRANCH[NBE6, $], c3; {Divide Dst Bitmapwidth by 4} TT ← RShift1 TT, SE ← 0, c1; Q ← uDstXLo, c2; Ybus ← TT - Q - 1, CarryBr, c3; {Check 1st X of Dst} Rx ← Q + Rx, BRANCH[NBE7, $], c1; Ybus ← TT - Rx, CarryBr, c2; {Check 2nd X of Dst} Q ← uDstYLo, BRANCH[NBE8, $], c3; LINE: Q ← Q + TOS, L0 ← L0NB3, c1; Rx ← uDBitMapHeight, c2; Q ← Rx - Q, c3; TOS ← uDBRasterWidth, CALL[MTPL], c1; {Calculate Y*Bitmaprasterwidth of Dst} Rx ← uDstYLo, c3, at[L0NB3, 10, MULCALLER]; TOS ← uTrnHeightLo, c1; TOS ← TOS - 1, c2; TOS ← TOS + Rx, c3; TOS ← TOS LShift1, SE ← 0, c1; PV ← TOS LShift1, SE ← 0, c2; {Multiply Y by 4} Rx ← uDstXLo, c3; Noop, c1; TOS ← uXoffset, c2; Rx ← Rx + TOS, c3; {Calculate the starting X for Dst} Rx ← Rx and 03, c1; Noop, c2; PV ← PV + Rx, YDisp, c3; Rx ← uDstXLo, DISP4[L3VAL, 8], c1; Rx ← Rx + TOS, L3 ← 00, c2, at[08, 10, L3VAL]; GOTO[DSCO], c3; {Current YXX = 000} Rx ← Rx + TOS, L3 ← 01, c2, at[09, 10, L3VAL]; GOTO[DSCO], c3; {Current YXX = 001} Rx ← Rx + TOS, L3 ← 02, c2, at[0A, 10, L3VAL]; GOTO[DSCO], c3; {Current YXX = 010} Rx ← Rx + TOS, L3 ← 03, c2, at[0B, 10, L3VAL]; GOTO[DSCO], c3; {Current YXX = 011} Rx ← Rx + TOS, L3 ← 04, c2, at[0C, 10, L3VAL]; GOTO[DSCO], c3; {Current YXX = 100} Rx ← Rx + TOS, L3 ← 05, c2, at[0D, 10, L3VAL]; GOTO[DSCO], c3; {Current YXX = 101} Rx ← Rx + TOS, L3 ← 06, c2, at[0E, 10, L3VAL]; GOTO[DSCO], c3; {Current YXX = 110} Rx ← Rx + TOS, L3 ← 07, c2, at[0F, 10, L3VAL]; GOTO[DSCO], c3; {Current YXX = 111} DSCO: Rx ← RShift1 Rx, SE ← 0, c1; {Divide X by 4} Rx ← RShift1 Rx, SE ← 0, c2; Q ← Rx + Q, CarryBr, c3; Rx ← uDBMBaseLo, BRANCH[NBNA1, NBA1], c1; {Load low word of base VA of Dst bitmap} NBA1: TT ← TT + 1, GOTO[NBCM1], c2; {Propagate carry to high word} NBNA1: Noop, c2; NBCM1: Rx ← Rx + Q, CarryBr, c3; {Set up low word of VA of Dst bitmap} Q ← uDBMBaseHi, BRANCH[NBNA2, NBA2], c1; {Load high word of base VA of Dst bitmap} NBA2: TT ← TT + 1, GOTO[NBCM2], c2; {Propagate carry to high word} NBNA2: Noop, c2; NBCM2: Q ← TT + Q, c3; rhTT ← Q LRot0, c1; {Set up high word of VA of Dst bitmap} urhDAddr ← Q, c2; {Save it} urDAddr ← Rx, c3; PXBK5: Map ← TT ← [rhTT, Rx], L1 ← L1.PX.NR.0A, c1; TOS ← uBITMAPRASTERWIDTH, L0 ← L0.PX.NR.0A, c2; {Save low word of VA for remapping} rhRx ← Rx ← MD, XwdDisp, c3; PXBK6: MAR ← Q ← [rhRx, TT + 0], DISP2[NBCH1], c1, at[L0.PX.NR.0A, 10, NRWMapFixCallerB2]; rDAddr ← Q, c2, at[1, 4, NBCH1]; {Save the low word of real address} DstReg ← MD, c3; {Fetch Dst} rhDAddr ← Rx LRot0, c1; {Save the high word of real address} Q ← uSrcYLo, L0 ← L0NB4, c2; TT ← uTrnHeightLo, c3; Rx ← uBITMAPHEIGHT, c1; Q ← TT + Q, c2; Q ← Rx - Q, c3; CALL[MTPL], c1; {Calculate Y*Bitmaprasterwidth of Src} TOS ← uSrcXLo, c3, at[L0NB4, 10, MULCALLER]; Rx ← uXoffset, c1; Rx ← TOS + Rx, YDisp, c2; {Calculate initial X of Src} DISP4[L2VAL, 0C], c3; L2 ← 0C, c1, at[0C, 10, L2VAL]; GOTO[SRCO], c2; {Current XX = 00} L2 ← 0D, c1, at[0D, 10, L2VAL]; GOTO[SRCO], c2; {Current XX = 01} L2 ← 0E, c1, at[0E, 10, L2VAL]; GOTO[SRCO], c2; {Current XX = 10} L2 ← 0F, c1, at[0F, 10, L2VAL]; GOTO[SRCO], c2; {Current XX = 11} SRCO: Rx ← RShift1 Rx, SE ← 0, c3; {Divide X by 4} Rx ← RShift1 Rx, SE ← 0, c1; Q ← Rx + Q, CarryBr, c2; Rx ← uBITMAPBASELO, BRANCH[NBNA3, NBA3], c3; NBA3: TT ← TT + 1, GOTO[NBCM3], c1; NBNA3: Noop, c1; NBCM3: Rx ← Rx + Q, CarryBr, c2; Q ← uBITMAPBASEHI, BRANCH[NBNA4, NBA4], c3; NBA4: TT ← TT + 1, GOTO[NBCM4], c1; NBNA4: Noop, c1; NBCM4: Q ← TT + Q, c2; rhTT ← Q LRot0, c3; urhSAddr ← Q, c1; {Save the high word of VA of Src for remapping} urSAddr ← Rx, c2; L1 ← L1.PX.NR.04, c3; PXBK7: Map ← TT ← [rhTT, Rx], c1; L0 ← L0.PX.NR.04, c2; {Save the low word of VA of Src for remapping} rhRx ← Rx ← MD, XwdDisp, c3; PXBK8: MAR ← Q ← [rhRx, TT + 0], DISP2[NBCH2], c1, at[L0.PX.NR.04, 10, NRWMapFixCallerB2]; rhSAddr ← Rx LRot0, c2, at[1, 4, NBCH2]; SrcReg ← MD, c3; {Fetch Src} rSAddr ← Q, L2Disp, c1; {Save the high word of real address of Src} DISP4[srcSel, 0C], c2; GOTO[SCO0], c3, at[0C, 10, srcSel]; {XX = 00} GOTO[SCO1], c3, at[0F, 10, srcSel]; {XX = 11} SrcReg ← SrcReg LRot12, GOTO[SCO2], c3, at[0E, 10, srcSel]; {XX = 10} SrcReg ← SrcReg LRot8, GOTO[SCO3], c3, at[0D, 10, srcSel]; {XX = 01} { ============================================================================================== Inner loop ============================================================================================== } {Case 1 : already have src nibl in SrcReg} SCO1: SrcReg ← SrcReg LRot4, L2 ← 0C, c1, at[0F, 10, srcNext]; {allign for curr nibl} {Current XX = 11, Next = 00} Rx ← SrcReg and 0F0, GOTO[GotSrcNibl], L3Disp, c2; {get nibl in bits 8-11} SCO2: SrcReg ← SrcReg LRot4, L2 ← 0F, c1, at[0E, 10, srcNext]; {allign for curr nibl} {Current XX = 10, Next = 11} Rx ← SrcReg and 0F0, GOTO[GotSrcNibl], L3Disp, c2; {get nibl in bits 8-11} SCO3: SrcReg ← SrcReg LRot4, L2 ← 0E, c1, at[0D, 10, srcNext];{allign for curr nibl} {Current XX = 01, Next = 10} Rx ← SrcReg and 0F0, GOTO[GotSrcNibl], L3Disp, c2; {get nibl in bits 8-11} {Case 2: need to read next src word} MAR ← rSAddr ← [rhSAddr, rSAddr + 1], c1, at[0C, 10, srcNext]; BRANCH[$, fixSAddr, 1], c2; SCONT: SrcReg ← MD, c3; SCO0: SrcReg ← SrcReg LRot8, L2 ← 0D, c1; {Current XX = 00, Next = 01} Rx ← SrcReg and 0F0, GOTO[GotSrcNibl], L3Disp, c2; {get src nibl in bits 8-11} GotSrcNibl: DISP4[dstNext, 04], c3; {First pass} DCO0: DstReg ← DstReg LRot4, c1, at[04, 10, dstNext]; {allign for curr nibl} {Current XX = 00, Next = 01} Q ← DstReg and 0F, GOTO[GotDstNibl], c2; {get nibl in bits 12-15} DCO1: DstReg ← DstReg LRot8, c1, at[05, 10, dstNext]; {allign for curr nibl} {Current XX = 01, Next = 10} Q ← DstReg and 0F, GOTO[GotDstNibl], c2; {get nibl in bits 12-15} DCO2: DstReg ← DstReg LRot12, c1, at[06, 10, dstNext]; {allign for curr nibl} {Current XX = 10, Next = 11} Q ← DstReg and 0F, GOTO[GotDstNibl], c2; {get nibl in bits 12-15} DCO3: DstReg ← DstReg LRot0, c1, at[07, 10, dstNext]; {Position the right nibble at bits 12 - 15} Q ← DstReg and 0F, GOTO[GotDstNibl], c2; {get dst nibl in bits 12-15} {Case 1: already have dst nibl in DstReg} DCO00: DstReg ← DstReg LRot4, c1, at[0C, 10, dstNext]; {allign for curr nibl} {Current XX = 00, Next = 01} Q ← DstReg and 0F, GOTO[GotDstNibl], c2; {get nibl in bits 12-15} DCO01: DstReg ← DstReg LRot4, c1, at[0D, 10, dstNext]; {allign for curr nibl} {Current XX = 01, Next = 10} Q ← DstReg and 0F, GOTO[GotDstNibl], c2; {get nibl in bits 12-15} DCO03: DstReg ← DstReg LRot4, c1, at[0E, 10, dstNext]; {allign for curr nibl} {Current XX = 10, Next = 11} Q ← DstReg and 0F, GOTO[GotDstNibl], c2; {get nibl in bits 12-15} {Case 2: need next dest word} DCO02: DstReg ← DstReg LRot4, c1, at[0F, 10, dstNext]; {allign for curr nibl} {Current XX = 10, Next = 11} Q ← DstReg and 0F, GOTO[GotDstNibl], c2; {get nibl in bits 12-15} { DCO03: MAR ← [rhDAddr, rDAddr + 0], c1, at[0F, 10, dstNext]; {write last value} MDR ← DstReg, c2; , c3; MAR ← rDAddr ← [rhDAddr, rDAddr + 1], c1; {read next value} BRANCH[$, fixDAddr, 1], c2; DstReg ← MD, c3; DCONT: DstReg ← DstReg LRot4, c1; {Position the right nibble at bits 12 - 15} Q ← DstReg and 0F, GOTO[GotDstNibl], c2; {get dst nibl in bits 12-15}} GotDstNibl: Rx ← Rx or Q, c3; {Concatenate Src and Dst} MAR ← [rhArray, Rx{src,,dst} + 0], c1; {Fetch entry from color table} DstReg ← DstReg and ~0F, L3Disp, c2; {erase orig value of Dst nibble} Rx{val} ← MD, DISP4[loc, 8], c3; CLY0: Rx ← Rx LRot4, L3 ← 09, c1, at[08, 10, loc]; Rx ← Rx and 0F, c2; {Current YXX = 000, Entry 0, Next: YXX = 001, Entry 1} DstReg ← DstReg or Rx, GOTO[entryready], c3; CLY1: Rx ← Rx LRot8, L3 ← 0A, c1, at[09, 10, loc]; Rx ← Rx and 0F, c2; {Current YXX = 001, Entry 1, Next: YXX = 010, Entry 0} DstReg ← DstReg or Rx, GOTO[entryready], c3; CLY2: Rx ← Rx LRot4, L3 ← 0B, c1, at[0A, 10, loc]; Rx ← Rx and 0F, c2; {Current YXX = 010, Entry 0, Next: YXX = 011, Entry 1} DstReg ← DstReg or Rx, GOTO[entryready], c3; CLY3: Rx ← Rx LRot8, L3 ← 08, c1, at[0B, 10, loc]; Rx ← Rx and 0F, c2; {Current YXX = 011, Entry 1, Next: YXX = 000, Entry 0} DstReg ← DstReg or Rx, c3; MAR ← [rhDAddr, rDAddr + 0], c1; {write} MDR ← DstReg, c2; , c3; MAR ← rDAddr ← [rhDAddr, rDAddr + 1], c1; {read next value} BRANCH[$, fixDAddr1, 1], c2; DstReg ← MD, GOTO[entryready], c3; CLY4: Rx ← Rx LRot12, L3 ← 0D, c1, at[0C, 10, loc]; Rx ← Rx and 0F, c2; {Current YXX = 100, Entry 2, Next: YXX = 101, Entry 3} DstReg ← DstReg or Rx, GOTO[entryready], c3; CLY5: Rx ← Rx LRot0, L3 ← 0E, c1, at[0D, 10, loc]; Rx ← Rx and 0F, c2; {Current YXX = 101, Entry 3, Next: YXX = 110, Entry 2} DstReg ← DstReg or Rx, GOTO[entryready], c3; CLY6: Rx ← Rx LRot12, L3 ← 0F, c1, at[0E, 10, loc]; Rx ← Rx and 0F, c2; {Current YXX = 110, Entry 2, Next: YXX = 111, Entry 3} DstReg ← DstReg or Rx, GOTO[entryready], c3; CLY7: Rx ← Rx LRot0, L3 ← 0C, c1, at[0F, 10, loc]; Rx ← Rx and 0F, c2; {Current YXX = 111, Entry 3, Next: YXX = 100, Entry 2} DstReg ← DstReg or Rx, c3; {insert new value} MAR ← [rhDAddr, rDAddr + 0], c1; {write} MDR ← DstReg, c2; , c3; MAR ← rDAddr ← [rhDAddr, rDAddr + 1], c1; {read next value} BRANCH[$, fixDAddr2, 1], c2; DstReg ← MD, GOTO[entryready], c3; entryready: Q ← upixelcount, c1; Q ← Q - 1, ZeroBr, c2; {Decrement pixel count} BRANCH[$, LNFN], c3; PXBKB: Noop , c1; L2Disp, c2; upixelcount ← Q, DISP4[srcNext, 0C], c3; {loop back} { ============================================================================================== Update # of lines ============================================================================================== } LNFN: Q ← uTrnWidthLo, L3Disp, c1; upixelcount ← Q, DISP4[DstAllign, 0C], c2; {Initialize pixel count} DstReg ← DstReg LRot0, GOTO[PXBKC], c3, at[0C, 10, DstAllign]; DstReg ← DstReg LRot4, GOTO[PXBKC], c3, at[0F, 10, DstAllign]; DstReg ← DstReg LRot8, GOTO[PXBKC], c3, at[0E, 10, DstAllign]; DstReg ← DstReg LRot12, GOTO[PXBKC], c3, at[0D, 10, DstAllign]; PXBKC: MAR ← [rhDAddr, rDAddr + 0], c1; {Write the last value} MDR ← DstReg, c2; Q ← uTrnHeightLo, c3; Q ← Q - 1, ZeroBr, c1; uTrnHeightLo ← Q, BRANCH[$, NBEX], c2; { ============================================================================================== Handle Interrupts ============================================================================================== } uXoffset ← 0, MesaIntBr, c3; Ybus ← uWDC, NZeroBr, BRANCH[NBNI1, $], c1; Ybus ← uWP, ZeroBr, BRANCH[$, NBNI2], c2; uWP ← 0, BRANCH[NBIN, NBNI3], c3; NBIN: TOS ← uTrnHeightLo, c1; TOSH ← uTOSH, c2; rhS ← nRhS, c3; Noop, c1; S ← uS, c2; Q ← 0, c3; MAR ← [rhS, S + 0], c1; MDR ← Q, c2; PV ← uPVx, c3; Bank ← EmuBank, c1; rhPV ← nRhS, c2; PC ← uPC, CROSS[EmuInt], c3; { ClrIntErr, Rx ← 1, c1, at[EmuInt]; uWDC ← Rx, c2; Rx ← KbdFXP, L2 ← 0, GOTO[PUNT], c3;} NBNI1: Q ← uDstYLo, CANCELBR[$], c2; TOS ← uTrnHeightLo, GOTO[LINE], c3; NBNI2: CANCELBR[$], c3; NBNI3: Q ← uDstYLo, c1; TOS ← uTrnHeightLo, c2; GOTO[LINE], c3; { ============================================================================================== Remap ============================================================================================== } fixDAddr1: uRx ← Rx, c3; PXS0: TT ← urDAddr, c1; {Retrieve original rDAddr} Q ← 0FF + 1, c2; {Load Q with 100} TT ← TT + Q, CarryBr, c3; {Add rDAddr with 100} Q ← urhDAddr, BRANCH[NBND1, NBAD1], c1; NBAD1: Q ← Q + 1, c2; Noop, c3; Noop, c1; NBND1: rhTT ← Q LRot0, c2; urhDAddr ← Q, c3; NBMP1: Map ← [rhTT, TT + 0], L1 ← L1.PX.NR.05, c1; urDAddr ← TT, L0 ← L0.PX.NR.05, c2; rhRx ← Rx ← MD, XwdDisp, c3; MAR ← Q ← [rhRx, rDAddr + 0], DISP2[NBMAP1], c1, at[L0.PX.NR.05, 10, NRWMapFixCallerB2]; rDAddr ← Q, c2, at[1, 4, NBMAP1]; DstReg ← MD, c3; Q ← rhRx, c1; rhDAddr ← Q LRot0, c2; Rx ← uRx, GOTO[entryready], c3; fixDAddr2: uRx ← Rx, c3; PXS1: TT ← urDAddr, c1; {Retrieve original rDAddr} Q ← 0FF + 1, c2; {Load Q with 100} TT ← TT + Q, CarryBr, c3; {Add rDAddr with 100} Q ← urhDAddr, BRANCH[NBND10, NBAD10], c1; NBAD10: Q ← Q + 1, c2; Noop, c3; Noop, c1; NBND10: rhTT ← Q LRot0, c2; urhDAddr ← Q, c3; NBMP10: Map ← [rhTT, TT + 0], L1 ← L1.PX.NR.06, c1; urDAddr ← TT, L0 ← L0.PX.NR.06, c2; rhRx ← Rx ← MD, XwdDisp, c3; MAR ← Q ← [rhRx, rDAddr + 0], DISP2[NBMAP3], c1, at[L0.PX.NR.06, 10, NRWMapFixCallerB2]; rDAddr ← Q, c2, at[1, 4, NBMAP3]; DstReg ← MD, c3; Q ← rhRx, c1; rhDAddr ← Q LRot0, c2; Rx ← uRx, GOTO[entryready], c3; { ================================================================================= Set up registers and memories ================================================================================= } PXS3: S ← uS, c1, at[L1.PX.NR.06, 10, NTrapFixesB2]; rhS ← nRhS, c2; Q ← upixelcount, c3; MAR ← [rhS, S + 0], c1; MDR ← Q - 1, c2; Q ← 0, c3; GOTO[RestoreAllRegsAndPFB2], c1; PXS4: S ← uS, c1, at[L1.PX.NR.05, 10, NTrapFixesB2]; rhS ← nRhS, c2; Q ← upixelcount, c3; MAR ← [rhS, S + 0], c1; MDR ← Q - 1, c2; Q ← 0, c3; GOTO[RestoreAllRegsAndPFB2], c1; fixSAddr: TT ← urSAddr, c3; {Retrieve original rSAddr} Q ← 0FF + 1, c1; {Load Q with 100} TT ← TT + Q, CarryBr, c2; {Add rSAddr with 100} Q ← urhSAddr, BRANCH[NBNS1, NBAS1], c3; NBAS1: Q ← Q + 1, c1; rhTT ← Q LRot0, c2; urhDAddr ← Q, GOTO[NBMP2], c3; NBNS1: rhTT ← Q LRot0, c1; Noop, c2; Noop, c3; NBMP2: Map ← [rhTT, TT + 0], L1 ← L1.PX.NR.07, c1; urSAddr ← TT, L0 ← L0.PX.NR.07, c2; rhRx ← Rx ← MD, XwdDisp, c3; MAR ← Q ← [rhRx, rSAddr + 0], DISP2[NBMAP2], c1, at[L0.PX.NR.07, 10, NRWMapFixCallerB2]; rSAddr ← Q, c2, at[1, 4, NBMAP2]; SrcReg ← MD, c3; Q ← rhRx, c1; rhSAddr ← Q LRot0, c2; GOTO[SCO0], c3; { ================================================================================= Set up registers and memories ================================================================================= } PXS5: S ← uS, c1, at[L1.PX.NR.07, 10, NTrapFixesB2]; rhS ← nRhS, c2; Q ← upixelcount, c3; MAR ← [rhS, S + 0], c1; MDR ← Q, c2; Q ← 0, c3; GOTO[RestoreAllRegsAndPFB2], c1; PXS6: S ← uS, c1, at[L1.PX.NR.0A, 10, NTrapFixesB2]; rhS ← nRhS, c2; Q ← upixelcount, c3; MAR ← [rhS, S + 0], c1; MDR ← Q, c2; Q ← 0, c3; GOTO[RestoreAllRegsAndPFB2], c1; PXS7: S ← uS, c1, at[L1.PX.NR.04, 10, NTrapFixesB2]; rhS ← nRhS, c2; Q ← upixelcount, c3; MAR ← [rhS, S + 0], c1; MDR ← Q, c2; Q ← 0, c3; GOTO[RestoreAllRegsAndPFB2], c1; NBCH3: CALL[RLMapFixB2], c2; GOTO[NRWLMapFixB2], c2, at[0, 4, NBCH1]; GOTO[NRWLMapFixB2], c2, at[2, 4, NBCH1]; GOTO[NRWLMapFixB2], c2, at[3, 4, NBCH1]; GOTO[NRWLMapFixB2], c2, at[0, 4, NBCH2]; GOTO[NRWLMapFixB2], c2, at[2, 4, NBCH2]; GOTO[NRWLMapFixB2], c2, at[3, 4, NBCH2]; GOTO[NRWLMapFixB2], c2, at[0, 4, NBMAP1]; GOTO[NRWLMapFixB2], c2, at[2, 4, NBMAP1]; GOTO[NRWLMapFixB2], c2, at[3, 4, NBMAP1]; GOTO[NRWLMapFixB2], c2, at[0, 4, NBMAP3]; GOTO[NRWLMapFixB2], c2, at[2, 4, NBMAP3]; GOTO[NRWLMapFixB2], c2, at[3, 4, NBMAP3]; GOTO[NRWLMapFixB2], c2, at[0, 4, NBMAP2]; GOTO[NRWLMapFixB2], c2, at[2, 4, NBMAP2]; GOTO[NRWLMapFixB2], c2, at[3, 4, NBMAP2]; { ================================================================================== Error cases ================================================================================== } NBYE1: S ← uS, GOTO[ufnX2], c1; NBYE2: S ← uS, GOTO[ufnX2], c1; NBXE1: S ← uS, GOTO[ufnX2], c1; NBXE2: S ← uS, GOTO[ufnX2], c1; NBPXE1: S ← uS, GOTO[ufnX2], c1; NBPXE2: S ← uS, GOTO[ufnX2], c1; NBTE1: S ← uS, GOTO[ufnX2], c1; NBTE2: S ← uS, CANCELBR[ufnX1, 3], c3; NBTE3: S ← uS, GOTO[ufnX2], c1; NBE1: S ← uS, c2; rhS ← nRhS, GOTO[ufnX1], c3; NBE2: S ← uS, GOTO[NBE09], c1; {rhS ← nRhS, GOTO[ufnX3], c2;} NBE3: S ← uS, GOTO[NBE09], c1; {rhS ← nRhS, GOTO[ufnX3], c2;} NBE7: Noop, c2; {S ← uS, c2; rhS ← nRhS, GOTO[ufnX1], c3;} NBE4: S ← uS, c3; rhS ← nRhS, GOTO[ufnX2], c1; NBE5: S ← uS, GOTO[NBE09], c1; {rhS ← nRhS, GOTO[ufnX3], c2;} NBE6: S ← uS, GOTO[NBE09], c1; {rhS ← nRhS, GOTO[ufnX3], c2;} NBE8: S ← uS, c1; NBE09: rhS ← nRhS, GOTO[ufnX3], c2; NOTR3: Noop, c1; NOTR1: S ← uS, GOTO[ufnX3], c2; NOTR4: Noop, c1; NOTR2: S ← uS, GOTO[ufnX3], c2; { NOTR1: S ← uS, GOTO[ufnX3], c2; NOTR2: S ← uS, GOTO[ufnX3], c2; NOTR3: S ← uS, GOTO[ufnX2], c1; NOTR4: S ← uS, GOTO[ufnX2], c1;} { ================================================================================== Exit ================================================================================== } NBEX: Q ← 18'd, c3; Xbus ← ib, GOTO[RestoreAllRegsAndExitB2], c1; { E N D }