:TITLE[JasmineHalftone];
%Edit by Fiala 16 July 1981: Harmonize with Pilot; change register assignments
to use more of available Stack registers; eliminate returnLoc register; add
prefix jh to register names.
Edit by Fiala 7 January 1981: Harmonize with Alto system; bum many mi.
Created by Maleson 3 April 1980.
Floyd-Steinberg error distribution halftoning,
"REPLACE" mode doesn’t work for all modes (save space)
%
SetTask[0];
*jhTemp1 (RM 5) and jhTemp2 (RM 7) are also used.
:IF[AltoMode]; **********************************
RV4[jhErrorVec,jhErrorVecHi,jhScreenWord,jhScreenWordHi,44];
RV4[jhBitCount,jhBitmapWidth,jhPixelArray,jhPixelArrayHi,50];
RV4[jhNInputPixels,jhBlackVal,jhRange,jhNOutputDots,10];
RV2[jhAddrTemp,jhAddrTempHi,14];
RV[jhCascadeRight,56];
RV[jhCascadeDiag,57];
RV[jhBitVal,66];
RV[jhJCtr,67];
RV[jhX,2];
RV[jhVal,3];
RV[jhErrorTemp,4];
RV[jhTemp1,5];
RV[jhTemp2,7];
:ELSE; ******************************************
*It seems that RM 6, 16-17 and 70-73 are available temporaries.
RV4[jhErrorVec,jhErrorVecHi,jhScreenWord,jhScreenWordHi,44];
RV4[jhBitCount,jhBitmapWidth,jhPixelArray,jhPixelArrayHi,50];
RV4[jhNInputPixels,jhBlackVal,jhRange,jhNOutputDots,10];
RV2[jhAddrTemp,jhAddrTempHi,14];
RV[jhCascadeRight,56];
RV[jhCascadeDiag,57];
RV[jhBitVal,66];
RV[jhJCtr,67];
RV[jhX,2];
RV[jhVal,3];
RV[jhErrorTemp,4];
RV[jhTemp1,5];
RV[jhTemp2,7];
:ENDIF; *****************************************
OnPage[HalftonePage];
***Find out whether MDShi should be used here and/or in Jasmine.Mc instead of
***0C for the high base register value.
@JHalfTone:
jhAddrTempHi ← 0C, At[PrintLine];
T ← Stack;
jhAddrTemp ← T;
PFetch4[jhAddrTemp,jhErrorVec,4];
PFetch4[jhAddrTemp,jhBitCount,10];
T ← LSh[jhErrorVecHi,10], Task;
jhErrorVecHi ← (jhErrorVecHi) + T + 1;
T ← LSh[jhScreenWordHi,10];
jhScreenWordHi ← (jhScreenWordHi) + T;*no +1, for negative adds;
PFetch4[jhAddrTemp,jhNInputPixels,0], Task;
T ← LSh[jhPixelArrayHi,10];
jhPixelArrayHi ← (jhPixelArrayHi) + T + 1;
T ← LdF[jhBitCount,14,4];
jhBitVal ← 17C;
jhBitVal ← (jhBitVal) - T;
CycleControl ← jhBitVal;
jhBitVal ← 100000C;
*jhBitVal ← 100000b rsh (jhBitCount[12d:15d])
jhBitVal ← WFA[jhBitVal];
T ← jhBitCount;
PFetch1[jhErrorVec,jhCascadeRight];
T ← jhNOutputDots;
jhJCtr ← (Zero) - T;
jhCascadeDiag ← Zero;
jhCascadeRight ← (LSh[jhCascadeRight,2]) - 1;
T ← jhNInputPixels;
jhTemp1 ← T;
T ← LdF[jhBitmapWidth,4,1];
jhNInputPixels ← (jhNInputPixels) + T;
jhX ← T, GoTo[forX0];
*subroutines: pieces used by all four modes
GetPixel:
T ← RSh[jhX,1], GoTo[xDone,ALU<0];
PFetch1[jhPixelArray,jhVal];
T ← jhBlackVal;
LU ← jhX, GoTo[xOdd,R Odd];
xEven:jhVal ← T ← (RSh[jhVal,10]) - T, GoTo[blackCheck];
xOdd:jhVal ← T ← (RHMask[jhVal]) - T, GoTo[blackCheck];
blackCheck:
LU ← (jhRange) - T, GoTo[blackOK,ALU>=0];
jhVal ← Zero, Return;
blackOK:
T ← jhRange, GoTo[whiteOK,ALU>=0];
jhVal ← T, Return;
whiteOK:Return;
OrBlack:
PFetch1[jhScreenWord,jhTemp2];
T ← jhBitVal;
jhTemp2 ← (jhTemp2) or T, Return;
NotWhite:
PFetch1[jhScreenWord,jhTemp2];
T ← jhBitVal;
jhTemp2 ← (jhTemp2) and not T, Return;
StoreVal:
PStore1[jhScreenWord,jhTemp2], Return;
GetError:
jhCascadeRight ← (RSh[jhCascadeRight,1]) or T, GoTo[a1,R Odd];
a0:T ← (RSh[jhCascadeRight,1]) or T, GoTo[a00,R Even];
a01:jhCascadeRight ← (jhCascadeRight) + 1;
a00:jhErrorTemp ← T, GoTo[haveError];
a1:T ← (RSh[jhCascadeRight,1]) or T, GoTo[a10,R Even];
a11:jhErrorTemp ← T ← (Zero) + T + 1, GoTo[haveError];
a10:jhCascadeRight ← (jhCascadeRight) + 1, GoTo[a00];
haveError:
jhCascadeDiag ← (jhCascadeDiag) + T;
T ← jhBitCount;
PStore1[jhErrorVec,jhCascadeDiag], Return;
GetNext:
PFetch1[jhErrorVec,jhTemp2];
T ← jhErrorTemp;
jhCascadeDiag ← T;
T ← jhTemp2;
jhCascadeRight ← (jhCascadeRight) + T;
T ← jhTemp1, Return;
xDone:LoadPageExternal[opPage3];
GoToExternal[P7TailLoc];
forX0:LU ← (jhNInputPixels) - T - 1, Call[GetPixel];
T ← jhJCtr, GoTo[jDone0,R>=0];
whileJ0:
T ← jhVal;
jhCascadeRight ← (jhCascadeRight) + T;
T ← jhRange, GoTo[White0,ALU>=0];
Black0: T ← LdF[jhBitCount,0,14], Call[OrBlack];
T ← LdF[jhBitCount,0,14], Call[StoreVal];
EndDot0:
T ← (jhCascadeRight) and (100000C), Call[GetError];
jhBitCount ← T ← (jhBitCount) + 1, Call[GetNext];
jhJCtr ← (jhJCtr) + T;
jhBitVal ← RCy[jhBitVal,1], GoTo[whileJ0,ALU<0];
jDone0:T ← jhNOutputDots;
jhJCtr ← (jhJCtr) - T;
jhX ← T ← (jhX) + 1, GoTo[forX0]; *could save 7 mi if jhJCtr still negative
White0: jhCascadeRight ← (jhCascadeRight) - T;
T ← LdF[jhBitCount,0,14], Call[NotWhite];
T ← LdF[jhBitCount,0,14];
PStore1[jhScreenWord,jhTemp2], GoTo[EndDot0];
:END[JasmineHalftone];