{  Filename: DrawLineB2.mc
   Description: Lisp line-drawing microcode.
   Author: Mitch Lichtenberg
   Creation date: 25-Jun-83 16:51:58
   
   Modified: 17-Apr-84  9:17:48
   
   Entry format:
     TOS  --> Maximum number of Y steps allowed {uYCount}
     SP-0 --> Maximum number of X steps allowed {uXCount}
     SP-2 --> Initial Delta {Delta}
     SP-4 --> Function number: {L2}
     		0: Set pixel
		1: Reset Pixel
		2: Invert Pixel
     SP-6 --> Relative Y coordinate of end of line (for the bucket) {uYT}
     SP-8 --> Width of bitmap (in words), signed to indicate Y direction {uYIncHi - uYIncLo}
     SP-10 -> Relative X coordinate of end of line (for the bucket) {uXT}
     SP-12 -> bit index [0..15] of bit to start at {CurBit}
     SP-14 -> Pointer to first word in bitmap {uPAdrHi - uPAdrLo}

	***   Registers used:

	Delta{TOSH}: contains the delta counter for determining step direction
	rhTT,,TT: contain the Virtual address of the word containing the pixel to modify
	rhRx,,Rx: contain the Real Address of the word containing the pixel,  and used as a temp reg
	CurBit{TOS}: contains the bit-mask for the current pixel

	uXT,uYT: values for X and Y slope {used to modify Delta}
	uXCount,uYCount: maximum pixels to be drawn in X/Y
	uYIncHi,uYIncLo: Y step value

	L0 holds Map update return value
	L1 holds Map fix for PFault value
	L2 holds Drawline Function {0: PAINT, 1: ERASE, 2,3: INVERT}
	L3 holds 2 if uYT > uXT {major direction}
}


{	IN BANK 1
@DRAWLINE:	opcode[73'b],
	Bank ← DLBank,	c1;
	uYCount ← TOS,	c2;
	S ← S - 14'd, CROSS[DLEntry],	c3;
}

	MAR ← [rhS,S + 0],	c1, at[DLEntry]; {- 14  Lo}
	Q ← 3, L0 ← L0.DLMap,	c2;  
	TT ← MD,	c3;

	MAR ← [rhS,S - 1],	c1; {- 14 Hi}
	S ← S + 2, CANCELBR[$, 2],	c2;  
	rhTT ← MD,	c3;

	MAR ← [rhS,S + 0],	{Get bitindex}		c1; {-12}
	S ← S + 2, L1 ← L1.DLFixesB2,	c2;  
	Rx ← MD,	c3;

{	convert value to bit mask in CurBit}
	CurBit ← RRot1 1,	c1;
dlCBloop:
	Rx ← Rx - 1, NegBr,	c2;
	BRANCH[dlCBshift, dlCBset],	c3;

dlCBshift:
	CurBit ← RRot1 CurBit, GOTO[dlCBloop],	c1;

dlCBset:
	MAR ← [rhS,S + 0],	{Get X bucket stepper}	c1; {-10}
	S ← S + 2,	c2;
	Rx ← MD,	c3;

	MAR ← [rhS,S - 1],	{Get Y Increment sign}		c1; {-8 Hi}
	uXT ← Rx, CANCELBR[$,2],	c2;  
	Xbus ← MD, XDisp, {width}	c3;

	MAR ← [rhS, S + 0], BRANCH[PosInc,NegInc,0E],		c1; {-8 Lo}

PosInc:
	uYIncHi ← 0,{Positive Increment} GOTO[GetY],	c2;

NegInc:
	uYIncHi ← ~TOS xor TOS,{Negative Increment} GOTO[GetY],	c2;

GetY:
	Rx ← MD, c3;

	,	c1;
	uYIncLo ← Rx, c2;
	S ← S + 2,	c3;

	MAR ← [rhS, S + 0],					c1; {-6}
	S ← S + 2,						c2;
	Rx ← MD, {Y bucket stepper}				c3;

	MAR ← [rhS,S + 0],					c1;  {-4}
	S ← S + 2,						c2;
	Q ← MD and Q{3},	c3; {Drawing function}

	MAR ← [rhS,S + 0],	c1; {-2}
	S ← S + 2,	c2;
	Delta ← MD,	c3; {Initial Delta}

	MAR ← [rhS,S + 0],	c1; {-0}
	Ybus ← Q, YDisp,	c2;
	Q ← MD, DISP2[DLsetL2], L2 ← 0{put function in L2},	c3; {X pixel count}

	uXCount ← Q, GOTO[dlhere],	c1, at[0, 4, DLsetL2]; 
	uXCount ← Q, GOTO[dlhere],	c1, at[1, 4, DLsetL2]; 
	uXCount ← Q, GOTO[dlhere],	c1, at[2, 4, DLsetL2]; 
	uXCount ← Q, GOTO[dlhere],	c1, at[3, 4, DLsetL2]; 

dlhere:
	Q ← uXT,  {Get X and Y bucket stepper values back}	c2;
	uYT ← Rx,	c3;

{Delta is in the range 0..MAX(XT,YT).. }

	Ybus ← Q - Rx, NegBr, {normalize delta}	c1;
	BRANCH[Xbig,Ybig],	c2;

Xbig:
	Delta ← Q - Delta - 1, GOTO[dlPlot], L3 ← 0,	c3;
Ybig:
	Delta ← Rx - Delta - 1, GOTO[dlPlottoo], L3 ← 2,	c3;

{All of the arguments are now set up.}

{=======================================================================}

dlPlottoo:
	Map ← [rhTT, TT], GOTO[dlPlot1],	c1;

dlPlot:
	Map ← [rhTT, TT], BRANCH[dlPlot1, dlXfixY],	c1;
dlPlot1:
	,	c2;
	rhRx ← Rx ← MD, XwdDisp{XDirtyDisp},	c3;

	MAR ← [rhRx, TT + 0], DISP2[DLMapFix],	c1, at[L0.DLMap, 10, WMapFixCallerB2];
	,	c2, at[1, 4, DLMapFix];
	Q ← MD, L2Disp,	c3;

	MAR ← [rhRx, TT + 0], DISP2[dlFnDisp], L3Disp,	c1;
	MDR ← Q or CurBit, BRANCH[dlXStuff, dlYStuff, 1],	c2, at[0, 4, dlFnDisp];
	MDR ← Q and ~CurBit, BRANCH[dlXStuff, dlYStuff, 1],	c2, at[1, 4, dlFnDisp];
	MDR ← Q xor CurBit, BRANCH[dlXStuff, dlYStuff, 1],	c2, at[2, 4, dlFnDisp];
	MDR ← Q xor CurBit, BRANCH[dlXStuff, dlYStuff, 1],	c2, at[3, 4, dlFnDisp];

{=======================================================================}

dlXStuff:
	Rx ← uXCount, GOTO[dlXS1], c3;
dlXStufftoo:
	Rx ← uXCount, GOTO[dlXS1], c3;

dlXS1:
	Rx ← Rx - 1, ZeroBr,	c1;
	uXCount ← Rx, BRANCH[$, dlXThru],	c2;
	CurBit ← RRot1 CurBit,	c3;

dlXS3:
	Ybus ← CurBit, NegBr, L3Disp,	c1;
	Rx ← uYT, DISP2[dlXDisp],	c2;
	TT ← TT + 1, CarryBr, GOTO[dlXmore],	c3, at[1, 4, dlXDisp];
	TT ← TT + 1, CarryBr, GOTO[dlXmore],	c3, at[3, 4, dlXDisp];

dlXmore:
	Q ← rhTT, BRANCH[dlXrhTTok, $], L3Disp,	c1;
	Q ← Q + 1, CANCELBR[$, 3],	c2;
	rhTT ← Q LRot0,	c3;

	L3Disp,	c1;
dlXrhTTok:
	DISP2[dlXDisp],	c2;

	Delta ← Delta - Rx, NegBr, GOTO[dlPlot],	c3, at[0, 4, dlXDisp];{X only}
	Delta ← Delta + Rx, GOTO[dlYrem],	c3, at[2, 4, dlXDisp];{X and Y}

dlXfixY:
	Rx ← uXT,	c2;
	Delta ← Delta + Rx, GOTO[dlYrem],	c3;

dlYStuff:
	Rx ← uXT,	c3;

	Delta ← Delta - Rx, NegBr,	c1;
	BRANCH[$, dlXStufftoo],	c2;
	,	c3;

dlYrem:
	Rx ← uYCount,	c1;
	Rx ← Rx - 1, ZeroBr,	c2;
	uYCount ← Rx, BRANCH[$, dlYThru],	c3;

	Rx ← uYIncLo,	c1;
	Q ← rhTT, 	c2;
	TT ← TT + Rx, CarryBr,	c3;

	Rx ← uYIncHi, BRANCH[dlYnocar, dlYcar],	c1;

dlYnocar:
	Q ← Q + Rx, GOTO[dlYdone],	c2;
dlYcar:
	Q ← Q + Rx + 1, GOTO[dlYdone],	c2;
dlYdone:
	rhTT ← Q LRot0, GOTO[dlPlot],	c3;

dlYThru:
	,	c1;
	,	c2;
dlXThru:
	Q ← rhTT, GOTO[dlNormExit],	c3;

{=======================================================================}


{MAP Update for DrawLine routine}
	GOTO[WLMapFixB2],	c2, at[0, 4, DLMapFix];
	GOTO[WLMapFixB2],	c2, at[2, 4, DLMapFix];
	GOTO[WLMapFixB2],	c2, at[3, 4, DLMapFix];

{uses standard remap routines now!
WMapDLFix: Xbus ← Rx LRot0, XwdDisp, 	c3;

	Map ← [rhTT,TT], DISP2[DLMFix],	c1;

	MDR ← Rx or {0B0}030, GOTO[Retry],	c2, at[0,4,DLMFix];
	MDR ← Rx or {0B0}030, GOTO[Retry],	c2, at[1,4,DLMFix];
	GOTO[DLTrap],	c2, at[2,4,DLMFix];
	GOTO[DLTrap],	c2, at[3,4,DLMFix];

Retry:	,	c3;
	MAR ← [rhRx, TT + 0], GOTO[GetWD],	c1;

{DLTrap : In the event of a page fault, we come here.}
DLTrap:
	,	c3;
uses standard remap routines now!}

	MAR ← [rhS,S + 0],	c1, at[L1.DLFixesB2, 10, TrapFixesB2]; {- 0}
	MDR ← uXCount,	c2;
	S ← S - 2,	c3;

	L3Disp,	c1;
	BRANCH[dlX, dlY, 1],	c2;
dlX:
	Q ← uXT, GOTO[dlSaveDelta],	c3;
dlY:
	Q ← uYT, GOTO[dlSaveDelta],	c3;

dlSaveDelta:
	MAR ← [rhS, S + 0],	c1; {- 2}
DelPos:
	MDR ← Q - Delta - 1, GOTO[DLcont],	c2;

DLcont:
	S ← S - 10'd,	c3;

	Rx ← 0,	c1;
dlSetBitLoop:
	Ybus ← CurBit, NegBr,	c2;
	CurBit ← LRot1 CurBit, BRANCH[dlAdd1toBit, dlBitok],	c3;

dlAdd1toBit:
	Rx ← Rx + 1, GOTO[dlSetBitLoop],	c1;

dlBitok:
	MAR ← [rhS, S + 0],	c1; {- 12}
	MDR ← Rx,	c2;
	S ← S - 2,	c3;

	MAR ← [rhS,S + 0],	c1; {- 14}
	MDR ← TT,	c2;
	S ← S - 1, L1 ← L1.NoFixes,	c3;

	MAR ← [rhS, S + 0],	c1;
	MDR ← rhTT,	c2;
	S ← S + 15'd,	c3;

	Bank ← EmuBank,	c1;
	TOSH ← smallpl, L1 ← L1.NoFixes,	c2;
	TOS ← uYCount, CROSS[PFaultB1],	c3;

{dlNormExit:  When we are finished drawing, execution comes here.
 The opcode returns the address of the end of the line.}

dlNormExit:
	Bank ← EmuBank,	c1;
	TOS ← TT,	c2; 
	TOSH ← Q, CROSS[DLExit],	c3;

{	IN BANK 1
	S ← S - 16'd,	c1, at[DLExit];
	L2 ← L2.0, PC ← PC + PC16, IBDisp,	c2;
	L2 ← L2.0, DISPNI[OpTable],	c3;
}


	{ E N D }