-- CGFullSampleImpl.mesa
-- Last edited by Ken Pier,
July 13, 1982 3:41 pm
-- Last edited by Doug Wyatt, May 28, 1982 10:16 am

DIRECTORY
CGFullSample USING [MapArray, Pointer],
Inline USING [BITAND, BITOR, BITXOR, LongMult, LongNumber];

CGFullSampleImpl: PROGRAM
IMPORTS Inline
EXPORTS CGFullSample = {

Line1: TYPE = RECORD[PACKED SEQUENCE COMPUTED NAT OF [0..1]];
Line2: TYPE = RECORD[PACKED SEQUENCE COMPUTED NAT OF [0..3]];
Line4: TYPE = RECORD[PACKED SEQUENCE COMPUTED NAT OF [0..17B]];
Line8: TYPE = RECORD[PACKED SEQUENCE COMPUTED NAT OF [0..377B]];

bit1: ARRAY [0..16) OF WORD ← [
100000B, 040000B, 020000B, 010000B, 004000B, 002000B, 001000B, 000400B,
000200B, 000100B, 000040B, 000020B, 000010B, 000004B, 000002B, 000001B];
bit0: ARRAY [0..16) OF WORD ← [
077777B, 137777B, 157777B, 167777B, 173777B, 175777B, 176777B, 177377B,
177577B, 177677B, 177737B, 177757B, 177767B, 177773B, 177775B, 177776B];

SAMPLE: PUBLIC PROC[p: CGFullSample.Pointer] = {
mFetch, bFetch, sFetch: BOOLEANFALSE;
dWord, mWord: LONG POINTER TO WORD;
di, mi: [0..16);
bLine, sBase, sLine: LONG POINTER;
map: LONG POINTER TO CGFullSample.MapArray;
bValue, sValue: CARDINAL;
size, count, bi, bw, sw, sh, sox, soy, sly, sRast: CARDINAL;
sx, sy, sdx, sdy: Inline.LongNumber;
fn0, fn1: [0..4);

count ← p.count; IF count=0 THEN RETURN;
fn0 ← p.function/4; fn1 ← p.function MOD 4; size ← p.size;
dWord ← p.dLine + p.di/16; di ← p.di MOD 16;

-- Set up for mask
IF p.mConst THEN NULL
ELSE { mWord ← p.mLine + p.mi/16; mi ← p.mi MOD 16; mFetch ← TRUE };

-- Set up for brick
IF p.bConst THEN bValue ← p.bValue
ELSE { bi ← p.bi; bw ← p.bw; bLine ← p.bLine; bFetch ← TRUE };

-- Set up for map
IF p.useMap THEN map ← p.map ELSE map ← NIL;

-- Set up for source
IF p.sConst THEN { sValue ← p.sValue; IF map#NIL THEN sValue ← map[sValue] }
ELSE { sBase ← p.sBase; sRast ← p.sRast;
sw ← p.sw; sh ← p.sh; sox ← p.sox; soy ← p.soy;
sx.li ← p.sx; sy.li ← p.sy; sdx.li ← p.sdx; sdy.li ← p.sdy;
sly ← LAST[CARDINAL]; sFetch ← TRUE };
-- maybe should test for sdx.high IN(-sw..sw), etc.

-- The sampling loop
DO
-- Test mask value
IF mFetch=FALSE OR Inline.BITAND[mWord^,bit1[mi]]#0 THEN {
-- Fetch source value
IF sFetch THEN {
IF sy.high#sly THEN { sly ← sy.high; sLine ← sBase + Inline.LongMult[sly+soy, sRast] };
SELECT size FROM
8 => sValue ← LOOPHOLE[sLine,LONG POINTER TO Line8][sx.high+sox];
1 => sValue ← LOOPHOLE[sLine,LONG POINTER TO Line1][sx.high+sox];
ENDCASE => ERROR; -- other sizes not implemented yet
IF map#NIL THEN sValue ← map[sValue];
};
-- Fetch brick value
IF bFetch THEN {
SELECT size FROM
8 => bValue ← LOOPHOLE[bLine,LONG POINTER TO Line8][bi];
1 => bValue ← LOOPHOLE[bLine,LONG POINTER TO Line1][bi];
ENDCASE => ERROR;
};
-- Compare
SELECT (IF sValue>bValue THEN fn1 ELSE fn0) FROM
0 => dWord^ ← Inline.BITAND[dWord^, bit0[di]]; --write zero bit
1 => NULL;
2 => dWord^ ← Inline.BITXOR[dWord^, bit1[di]]; --complement bit
3 => dWord^ ← Inline.BITOR[dWord^, bit1[di]]; --write one bit
ENDCASE => ERROR;
};
-- Terminate loop?
IF (count ← count - 1)=0 THEN EXIT;
-- Bump destination position
di ← (di+1) MOD 16; IF di=0 THEN dWord ← dWord+1;
-- Bump mask position
IF mFetch THEN { mi ← (mi+1) MOD 16; IF mi=0 THEN mWord ← mWord+1 };
-- Bump brick position
IF bFetch THEN { bi ← bi+1; IF bi=bw THEN bi ← 0 };
-- Bump source position
IF sFetch THEN {
sx.li ← sx.li + sdx.li; sy.li ← sy.li + sdy.li;
IF sx.high>=sw THEN sx.high ← sx.high - sw
ELSE IF sx.high<0 THEN sx.high ← sx.high + sw;
IF sy.high>=sh THEN sy.high ← sy.high - sh
ELSE IF sy.high<0 THEN sy.high ← sy.high + sh;
};
ENDLOOP;
};

}.