{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 }