:TITLE[JasmineHalftone];
*Last edited by Fiala 7 January 1981, by Maleson 3 April 1980

*Floyd-Steinberg error distribution halftoning,
*	"REPLACE" mode,
*	doesn't work for all modes (save space)

*Available RM Temps: 44-53 56-57, 66-73; available Unused: 0
**These assignments require that the Mesa stack must not be allowed longer
**than 4 words when this code is run.

RV4[errorVec,errorVecHi,screenWord,screenWordHi,44];
RV4[bitCount,bitmapWidth,pixelArray,pixelArrayHi,50];
RV4[nInputPixels,blackVal,range,nOutputDots,10];

RV2[AddrTemp,AddrTempHi,14];

RV[CascadeRight,56];
RV[CascadeDiag,57];
RV[bitVal,66];
RV[jctr,67];
RV[x,70];
RV[val,71];
RV[errorTemp,72];
RV[returnLoc,73],

SetTask[0];
OnPage[HalftonePage];

*halftone stuff
	AddrTempHi ← 0C, At[PrintLine];
	T ← Stack;
	AddrTemp ← T, UseCTask;
	T ← APCTask&APC;
	returnLoc ← T;
	PFetch4[AddrTemp,errorVec,4];
	PFetch4[AddrTemp,bitCount,10];
	T ← LSh[errorVecHi,10], Task;
	errorVecHi ← (errorVecHi) + T + 1;
	T ← LSh[screenWordHi,10];
	screenWordHi ← (screenWordHi) + T;	*no +1, for negative adds;
	PFetch4[AddrTemp,nInputPixels,0], Task;
	T ← LSh[pixelArrayHi,10];
	pixelArrayHi ← (pixelArrayHi) + T + 1;
	T ← LdF[bitCount,14,4];
	bitVal ← 17C;
	bitVal ← (bitVal) - T;
	CycleControl ← bitVal;
	bitVal ← 100000C;
*bitVal ← 100000b rsh (bitCount[12d:15d])
	bitVal ← WFA[bitVal];
	T ← bitCount;
	PFetch1[errorVec,CascadeRight];
	T ← nOutputDots;
	jctr ← (Zero) - T;
	CascadeDiag ← Zero;
	CascadeRight ← (LSh[CascadeRight,2]) - 1;
	T ← nInputPixels;
	Stack4 ← T;
	T ← LdF[bitmapWidth,4,1];
	nInputPixels ← (nInputPixels) + T; 
	x ← T, Goto[forX0];

*subroutines: pieces used by all four modes
GetPixel:
	T ← RSh[x,1], Goto[xDone,ALU<0];
	PFetch1[pixelArray,val];
	T ← blackVal;
	LU ← x, Goto[xOdd,R Odd];
xEven:	val ← T ← (RSh[val,10]) - T, Goto[blackCheck];
xOdd:	val ← T ← (RHMask[val]) - T, Goto[blackCheck];
blackCheck:
	LU ← (range) - T, Goto[blackOK,ALU>=0];
	val ← Zero, Return;
blackOK:
	T ← range, Goto[whiteOK,ALU>=0];
	val ← T, Return;
whiteOK:
xDone1:	Return;

OrBlack:
	PFetch1[screenWord,Stack6];
	T ← bitVal;
	Stack6 ← (Stack6) or T, Return;

NotWhite:
	PFetch1[screenWord,Stack6];
	T ← bitVal;
	Stack6 ← (Stack6) and not T, Return;

StoreVal:
	PStore1[screenWord,Stack6], Return;

GetError: 
	CascadeRight ← (RSh[CascadeRight,1]) or T, Goto[a1,R Odd];
a0:	T ← (RSh[CascadeRight,1]) or T, Goto[a00,R Even];
a01:	CascadeRight ← (CascadeRight) + 1;
a00:	errorTemp ← T, Goto[haveError];

a1:	T ← (RSh[CascadeRight,1]) or T, Goto[a10,R Even];
a11:	errorTemp ← T ← (Zero) + T + 1, Goto[haveError];
a10:	CascadeRight ← (CascadeRight) + 1, Goto[a00];
haveError:
	CascadeDiag ← (CascadeDiag) + T;	
	T ← bitCount;
	PStore1[errorVec,CascadeDiag], Return;
GetNext:
	PFetch1[errorVec,Stack6];
	T ← errorTemp;
	CascadeDiag ← T;
	T ← Stack6;
	CascadeRight ← (CascadeRight) + T;
	T ← Stack4, Return;

xDone:	APCTask&APC ← returnLoc, Goto[xDone1];

forX0:	LU ← (nInputPixels) - T - 1, Call[GetPixel];
	T ← jctr, Goto[jDone0,R>=0];
whileJ0: 
	T ← val;
	CascadeRight ← (CascadeRight) + T;
	T ← range, Goto[White0,ALU>=0];
Black0: T ← LdF[bitCount,0,14], Call[OrBlack];
	T ← LdF[bitCount,0,14], Call[StoreVal];
EndDot0:
	T ← (CascadeRight) AND (100000C), Call[GetError];
	bitCount ← T ← (bitCount) + 1, Call[GetNext];
	jctr ← (jctr) + T;
	bitVal ← RCy[bitVal,1], Goto[whileJ0,ALU<0];
jDone0:	T ← nOutputDots;
	jctr ← (jctr) - T;
	x ← T ← (x) + 1, Goto[forX0]; *could save 7 instructions if jctr still negative

White0: CascadeRight ← (CascadeRight) - T;
	T ← LdF[bitCount,0,14], Call[NotWhite];
	T ← LdF[bitCount,0,14];
	PStore1[screenWord,Stack6], Goto[EndDot0];

:END;