{
File : LispBitMapBit.mc
Author : Gunawan Santosa
Created : 26-Feb-85 14:05:34
================================================================================================
(BITMAPBIT BitMap X Y NewValue)
================================================================================================
if 0 =< NewValue =< max value for a pixel
then: Pixel(X, Y) ← NewValue
return old Pixel(X, Y)
if NewValue = NIL
then: return Pixel(X, Y)
else ERROR {UFN}
in case (X, Y) outside BitMap
then return 0 (and no mods)
NOTE: BitMap can also be a window
UFN in this case!
"BitMap" is a six word record of the following format:
0: BitMapBaseHi -- High word of Virtual Addr of [0, 0] of BitMap {upper left screen corner}
1: BitMapBaseLo -- Low word of Virtual Addr of [0, 0] of BitMap {upper left screen corner}
2: BitMapRasterWidth (words)
3: BitMapHeight (lines)
4: BitMapWidth (Pixels)
5: BitMapBitsPerPixel ({1 or 4 or 8})
fetch stack parameters:
S - 4: BitMap
S - 2: X
S - 0: Y
TOS: NewValue
Test that the TYPE of BitMap = BitMapType
fetch BitMap parameters:
BitMapBaseHi -- High word of Virtual Addr of [0, 0] of BitMap {upper left screen corner}
BitMapBaseLo -- Low word of Virtual Addr of [0, 0] of BitMap {upper left screen corner}
BitMapRasterWidth (words)
BitMapHeight (lines)
BitMapWidth (Pixels)
BitMapBitsPerPixel ({1 or 4 or 8})
calculate word-address of pixel, and pixel-mask
read old pixel value
store new pixel value if appropriate
}
Set[BitMapType, 35'd]; {For BitMapBit}
Set[L0.BMMULT0, 5]; {For BitMapBit}
Set[L0.BMMULT1, 6]; {For BitMapBit}
Set[L0.BMB.NR.0B, 0B]; {For BitMapBit}
Set[L0.GBMP, 9]; {For BitMapBit}
RegDef[uBITMAPLO, U, 3A]; {For BitMapBit, low VA of Bitmap, tmp}
RegDef[uBITMAPHI, U,3B]; {For BitMapBit, high VA of Bitmap, tmp}
RegDef[uYLo, U, 57]; {For BitMapBit, low word of Y, tmp}
RegDef[uBITMAPBASELO, U, 42]; {For BitMapBit, low VA of Bitmapbase, tmp}
RegDef[uBITMAPBASEHI, U, 44]; {For BitMapBit, high VA of Bitmapbase, tmp}
RegDef[uBITMAPRASTERWIDTH, U, 2]; {For BitMapBit, Bitmaprasterwidth, tmp}
RegDef[uBITMAPHEIGHT, U, 3]; {For BitMapBit, Bitmapheight, tmp}
RegDef[uBITMAPWIDTH, U, 34]; {For BitMapBit, Bitmapwidth, tmp}
RegDef[uBITMAPBITSPERPIXEL, U, 7]; {For BitMapBit, Bitmapbitsperpixel, tmp}
RegDef[uDBMBaseLo, U, 30]; {For BitMapBit, low VA of Bitmapbase, tmp}
RegDef[uDBMBaseHi, U, 51]; {For BitMapBit, high VA of Bitmapbase, tmp}
RegDef[uDBRasterWidth, U, 53]; {For BitMapBit, Bitmaprasterwidth, tmp}
RegDef[uDBitMapHeight, U, 56]; {For BitMapBit, Bitmapheight, tmp}
RegDef[uDBitMapWidth, U, 55]; {For BitMapBit, Bitmapwidth, tmp}
RegDef[uDBitsPerPixel, U, 59]; {For BitMapBit, Bitmapbitsperpixel, tmp}
RegDef[uTT1, U, 47]; {For BitMapBit, tmp}
RegDef[uMASKL, U, 45]; {For BitMapBit, tmp}
RegDef[uZ, U, 35]; {For BitMapBit, tmp}
{
=======================================================================
Fetch BitMap, X, Y, and NewValue
=======================================================================
@FLOATARRAY2: opcode[373'b],
Bank ← FAOPBank, L1 ← 3{L1.LFA2prep}, c1;
uTOS ← TOS, c2;
uTOSH ← TOSH, CROSS[FOP2], c3;
at[FOP2],
Xbus ← ibNA, XDisp, c1;
DISP4[FOP2Disp], L2 ← 0, c2;
}
TT ← S, rhTT ← nRhS, c3, at[06, 10, FOP2Disp];
{Link value for Bitmap parameters fetch}
BR000: MAR ← [rhS, S-1], L1 ← L1.NoFixesB2, c1; {Point to high word of Y}
TT ← TT - 2, CANCELBR[$, 2], c2; {Prepare TT to fetch X}
Q ← MD, c3;
MAR ← [rhS, S+0], L3 ← 0, c1; {Point to low word of Y}
Ybus ← Q xor smallpl, ZeroBr, c2;
Q ← MD, BRANCH[YNOK, $], c3;
MAR ← [rhTT, TT-1], c1; {Point to high word of X}
uYLo ← Q, CANCELBR[$, 2], c2; {uYLo is low word of Y}
Rx ← MD, c3;
MAR ← [rhTT, TT+0], c1; {Point to low word of X}
TT ← TT-2, L2 ← 6, c2; {Prepare TT to fetch BitMap}
Q ← MD, c3;
MAR ← [rhTT, TT-1], c1;
Ybus ← Rx xor smallpl, CANCELBR[$, 2], ZeroBr, c2; {uXLo is low word of X}
Rx ← MD, BRANCH[XNOK, $], c3; {Rx is high VA of BitMap}
MAR ← [rhTT, TT+0], c1;
uXLo ← Q, c2; {uXHi is high word of X}
TT ← MD, CALL[GetandTestBitMapParams], c3; {TT is low VA of BitMap}
{Check Type of Bitmap and fetch Record}
Ybus ← Q - 1, ZeroBr, c3, at[6, 10, GetBitMapParamsRet];
{Q contains value of Bitsperpixel}
{
======================================================
Determine bits per pixel value
======================================================
}
Ybus ← Q xor 4, ZeroBr, BRANCH[$, OneBitperPixel], c1;
Ybus ← Q xor 8, ZeroBr, BRANCH[$, FourBitsperPixel], c2;
TT ← RRot1 uXLo, BRANCH[IllegalBitsperPixel, EightBitsperPixel], c3; {Divide X by 2}
OneBitperPixel:
uMASKL ← Q, CANCELBR[$], c2; {Load initial mask value (=1)}
TT ← uXLo, GOTO[bmbvalchk], c3; {Load X into TT}
FourBitsperPixel:
Q ← 0F, CANCELBR[$], c3; {Load initial mask value (=0000000000001111)}
uMASKL ← Q, c1;
TT ← LShift1 uXLo, SE ← 0, c2; {Divide X by 4}
TT ← LShift1 TT, SE ← 0, GOTO[bmbvalchk], c3; {Load the result into TT}
EightBitsperPixel:
Q ← 0FF, c1; {Load initial mask value (=0000000011111111)}
uMASKL ← Q, c2;
TT ← TT LRot4, GOTO[bmbvalchk], c3; {Multiply TT by 16}
bmbvalchk:
Rx ← uBITMAPWIDTH, c1; {Check if X inside Bitmap}
Ybus ← Rx - TT - 1, CarryBr, c2;
uZ ← TT, BRANCH[XValTooBig, $], c3; {uZ = X * Bits per pixel}
TT ← TT and ~0F, c1; {Divide TT by 16}
TT ← TT LRot12, c2;
uXLo ← TT, c3; {uXLo = X * Bits per pixel / 16}
Ybus ← Q - TOS, CarryBr, c1; {Check if NewValue doesn't exceed max value}
Rx ← uYLo, BRANCH[PixelValueTooBig, $], c2;
TT ← uBITMAPHEIGHT, L0 ← L0.BMMULT0, c3;
Q ← TT - Rx - 1, CarryBr, c1;{Calculate the Y offset}
TOS ← uBITMAPRASTERWIDTH, BRANCH[YValTooBig, $], c2;
CALL[MTPL], c3; {Y*Bitmaprasterwidth}
{
================================================================================
Calculate address of pixel(X,Y)
================================================================================
Address = (Y*BITMAPRASTERWIDTH + (X*BITMAPBITSPERPIXEL)/16)+BITMAPBASE}
Rx ← uXLo, L1 ← L1.RestoreTosB2, c2, at[L0.BMMULT0, 10, MULCALLER];
Rx ← Rx + Q, CarryBr, c3; {Start adding}
Q ← uBITMAPBASELO, BRANCH[RXNC1, RXCR1], c1; {Load low word of base address}
RXNC1: GOTO[ADCL], c2; {No carry to high order word}
RXCR1: TT ← TT + 1, c2; {Propagate carry to high order word}
ADCL: Rx ← Rx + Q, CarryBr, c3; {Set up low word of address}
AD11: Q ← uBITMAPBASEHI, BRANCH[RXNC2, RXC2], c1; {Load high word of base address}
RXNC2: TT ← TT + Q, GOTO[HINC1], c2;
RXC2: TT ← TT + Q + 1, c2; {Propagate carry to high word}
HINC1: rhTT ← TT LRot0, GOTO[HINC2], c3; {Set up high word of address}
{
================================================================================
Read pixel(X,Y)
================================================================================
}
HINC2: Map ← TT ← [rhTT, Rx], c1;
L0 ← L0.BMB.NR.0B, c2;
rhRx ← Rx ← MD, XwdDisp, c3;
MAR ← Q ← [rhRx, TT + 0], DISP2[BMCHCK], c1, at[L0.BMB.NR.0B, 10, NRWMapFixCallerB2];
uRx ← Q, c2, at[1, 4, BMCHCK];
TT ← MD, c3; {Store it in TT}
Rx ← uBITMAPBITSPERPIXEL , c1;
Q ← uZ, L0 ← 0A, c2; {Retrieve X*Bits per pixel}
Rx ← Q + Rx, YDisp, c3;
{
==========================================================================
Allign old pixels values
==========================================================================
Rotate left by : (((X*Bitsperpixel) mod 16) + Bitsperpixel) mod 16)
}
Q ← uMASKL, DISP4[Allign], c1; {Allign old pixel value to right hand side}
uTTtmp ← TT, c2, at[0A, 10, AllignRet]; {Save the entire word}
TT ← TT and Q, c3; {Mask off unwanted bits}
uTT1 ← TT, c1; {Save the old value}
Ybus ← TOSH xor smallpl, ZeroBr, c2; {Check if TOSH = 0E}
TOS ← uTOS, BRANCH[TSQN, TSOK], c3; {Retrieve new value}
{
=========================================================================
Allign new pixels values
=========================================================================
Rotate left by: (16 - Bitsperpixel) - ((X*Bitsperpixel) mod 16)
}
TSOK: Q ← uTTtmp, c1; {Retrieve the old word}
TT ← Q - TT, c2; {Mask off old value}
TT ← TT or TOS, L0 ← 0B, c3; {Put the new value in}
Ybus ← 0 - Rx, YDisp, c1;
Rx ← uRx, DISP4[Allign], c2; {Allign the new word, restore Rx}
S ← S - 6, GOTO[WrNV], c3, at[0B, 10, AllignRet]; {Write new word}
TSQN: Ybus ← TOSH or TOS, ZeroBr, c1; {Check if new value is NIL}
BRANCH[TSNK, TSN], c2;
TSN: TOSH ← smallpl, c3; {Set up TOSH}
Xbus ← ib, c1;
TOS ← uTT1, c2; {Return old value of pixel (X,Y)}
S ← S - 6, GOTO[c1.pc2B2], c3; {Exit point when NewValue is NIL}
TSNK: GOTO[ufnZ1], c3;
{
=======================================================================
Write NewValue into pixel(X, Y)
=======================================================================
}
WrNV: MAR ← [rhRx, Rx + 0], c1;
MDR ← TT , Xbus ← ib, c2; {Write it}
TOS ← uTT1, GOTO[c1.pc2B2], c3; {Exit point is here}
{
==============================================
(X,Y) is outside BITMAP or invalid number
==============================================
If X or Y is outside BITMAP, return 0.
}
XNOK: GOTO[ufnX2], c1;
YNOK: GOTO[ufnX2], c1;
XYER12: TOS ← 0, Xbus ← ib, c1; {If (X,Y) outside bitmap, return 0}
TOSH ← smallpl, c2;
S ← S - 6, GOTO[c1.pc2B2], c3;
XYER13: TOS ← 0, Xbus ← ib, c1; {If (X,Y) outside bitmap, return 0}
bmbsettosh:
TOSH ← smallpl, c2;
S ← S - 6, GOTO[c1.pc2B2], c3;
{
======================================================================
Bitmapbitsperpixel other than 1, 4 or 8, or NewValue exceeds max value
======================================================================
}
IllegalBitsperPixel:
GOTO[ufnX2], c1;
PixelValueTooBig:
GOTO[ufnX1], c3;
XValTooBig:
TOS ← 0, Xbus ← ib, GOTO[bmbsettosh], c1;
YValTooBig:
TOS ← 0, Xbus ← ib, c3;
GOTO[bmbsettosh], c1;
{
=======================================================================
Map check
=======================================================================
}
GOTO[NRWLMapFixB2], c2, at[0, 4, BMCHCK];
GOTO[NRWLMapFixB2], c2, at[2, 4, BMCHCK];
GOTO[NRWLMapFixB2], c2, at[3, 4, BMCHCK];
{
=======================================================================
Multiplier subroutine
=======================================================================
Q = multiplicand
TOS = multiplier
Rx = counter
(TT Q) contains the result, Q is least significant word.
}
MTPL: Rx ← 10, c*{c1};
TT ← 0, c*{c2};
MLLP: Ybus ← Q and 1, NZeroBr, c*{c3};
Rx ← Rx - 1, ZeroBr, BRANCH[MPL0, MPL1], c*{c1};
MPL0: TT ← DARShift1 (TT + 0), BRANCH[MLLP, MLPE], c*{c2};
MPL1: TT ← DARShift1 (TT + TOS), BRANCH[MLLP, MLPE], c*{c2};
MLPE: Q ← ~Q, L0Disp, c*{c3};
RET[MULCALLER], c*{c1};
{
=======================================================================
Test type of Bitmap and fetch record of Bitmap
=======================================================================
subroutine to check BitMap type and get BitMap parameters
Rx, TT have VA of BitMapTable
L3 ← 0{Src}/1{Dst} has six or'd in at exit
L2 used for return
uses NoFixes if PageFault
trashes L0, L1, TT, Rx, Q, rhTT, rhRx
values from table are placed into:
if Src then : uBITMAPBASEHI if Dst then : uDBMBaseHi
uBITMAPBASELO uDBMBaseLo
uBITMAPRASTERWIDTH uDRasterWidth
uBITMAPHEIGHT uDBitMapHeight
uBITMAPWIDTH uDBitMapWidth
uBITMAPBITSPERPIXEL uDBitsPerPixel
Set[L0.GBMP, 09];{must be odd! uses even also}}
GetandTestBitMapParams:
MAR ← Q ← [TT, Rx + 0], c1;{not mem ref, byte merge}
rhTT ← Rx LRot0, c2;
Rx ← Q, rhRx ← crhTypeTable, c3;
Rx ← Rx LRot8, c1;
Rx ← Rx RShift1, getTypemsBit, c2;
Q ← 0FF, c3;
MAR ← [rhRx, Rx + 0], c1;
Rx ← BitMapType, c2;
Rx ← MD xor Rx, c3;
GetBitMapParams:
Map ← [rhTT, TT], L1 ← L1.NoFixesB2, c1;
Ybus ← Q and Rx, ZeroBr, L0 ← L0.GBMP, c2;
Rx ← rhRx ← MD, XRefBr, BRANCH[notBitMapufn, $], c3;
MAR ← Q ← [rhRx, TT + 0], BRANCH[GBMremapit, $], c1, at[L0.GBMP, 10, RMapFixCallerB2];
Rx ← Q, L3Disp, c2;
Q ← MD, L3Disp, DISP3[GBMfixitret, 1] c3;
MAR ← Rx ← [rhRx, Rx + 1], BRANCH[$, GBMdest1], c1, at[1, 8, GBMfixitret];
uBITMAPBASEHI ← Q, CANCELBR[$, 2], c2;
GBMdest1ret:
Q ← MD, L3Disp, c3;
MAR ← Rx ← [rhRx, Rx + 1], BRANCH[$, GBMdest2], c1;
uBITMAPBASELO ← Q, BRANCH[$, GBMfixitA, 1], c2;
GBMdest2ret:
Q ← MD, L3Disp, c3;
MAR ← Rx ← [rhRx, Rx + 1], BRANCH[$, GBMdest3, 2], c1, at[3, 8, GBMfixitret];
uBITMAPRASTERWIDTH ← Q, CANCELBR[$, 2], c2;
GBMdest3ret:
Q ← MD, L3Disp, c3;
MAR ← Rx ← [rhRx, Rx + 1], BRANCH[$, GBMdest4, 6], L3 ← 6, c1;
uBITMAPHEIGHT ← Q, BRANCH[$, GBMfixitB, 1], c2;
GBMdest4ret:
Q ← MD, L3Disp, c3;
MAR ← [rhRx, Rx + 1], BRANCH[$, GBMdest5, 6], c1, at[7, 8, GBMfixitret];
uBITMAPWIDTH ← Q, CANCELBR[$, 2], c2;
GBMdest5ret:
Q ← MD, L3Disp, c3;
BRANCH[$, GBMdest6, 6], L2Disp, c1;
uBITMAPBITSPERPIXEL ← Q, DISP4[GetBitMapParamsRet], c2;
GBMdest1:
uDBMBaseHi ← Q, CANCELBR[GBMdest1ret, 2], c2;
GBMdest2:
uDBMBaseLo ← Q, BRANCH[GBMdest2ret, GBMfixitA, 1], c2;
GBMdest3:
uDBRasterWidth ← Q, CANCELBR[GBMdest3ret, 2], c2;
GBMdest4:
uDBitMapHeight ← Q, BRANCH[GBMdest4ret, GBMfixitB, 1], c2;
GBMdest5:
uDBitMapWidth ← Q, CANCELBR[GBMdest5ret, 2], c2;
GBMdest6:
uDBitsPerPixel ← Q, DISP4[GetBitMapParamsRet], c2;
GBMremapit:
CALL[RLMapFixB2], c2;
GBMfixitA:
TT ← TT and ~0FF, GOTO[GBMallfixit], c3;
GBMfixitB:
TT ← TT and ~0FF, GOTO[GBMallfixit], c3;
GBMallfixit:
Q ← 0FF + 1, c1;
TT ← TT + Q, CarryBr, c2;
Rx ← 0, BRANCH[GetBitMapParams, GBMfixrh], c3;
GBMfixrh:
Q ← rhTT, c1;
Q ← Q + 1, c2;
rhTT ← Q LRot0, GOTO[GetBitMapParams], c3;
notBitMapufn:
CANCELBR[ufnX2, 3], c1;
{END}