{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, NegBr, 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, L2 ← L2NBRET1, 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;
, 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, NegBr, c3;
PXBKE: TT ← TOS + TT, BRANCH[$, NBE1], c1; {TOS = TrnHeight}
Ybus ← Q - TT, NegBr, c2; {Check 2nd Y of Src}
TT ← uDstYLo, BRANCH[$, NBE2], c3; {Load Y Dst}
Q ← uDBitMapHeight, c1;
Ybus ← Q - TT - 1, NegBr, c2; {Check 1st Y of Dst}
TT ← TOS + TT, BRANCH[$, NBE3], c3;
Ybus ← Q - TT, NegBr, 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, NegBr, c2; {Check 1st X of Src}
Rx ← uTrnWidthLo, BRANCH[$, NBE5], c3;
Q ← Q + Rx, c1;
Ybus ← TT - Q, NegBr, 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, NegBr, c3; {Check 1st X of Dst}
Rx ← Q + Rx, BRANCH[$, NBE7], c1;
Ybus ← TT - Rx, NegBr, 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;
Rx ← Rx and 03, c1;
Noop, c2;
Noop, c3;
TOS ← uXoffset, c1;
Rx ← Rx + TOS, c2; {Calculate the starting X for Dst}
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;
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;
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
=================================================================================
}
S ← uS, c1, at[L1.PX.NR.06, 10, NTrapFixesB2];
rhS ← nRhS, c2;
Q ← upixelcount, c3;
MAR ← [rhS, S + 0], c1;
MDR ← Q, c2;
Q ← 0, c3;
GOTO[RestoreAllRegsAndPFB2], c1;
S ← uS, c1, at[L1.PX.NR.05, 10, NTrapFixesB2];
rhS ← nRhS, c2;
Q ← upixelcount, c3;
MAR ← [rhS, S + 0], c1;
MDR ← Q, 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
=================================================================================
}
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;
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;
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 }