.PREL .IDENT GRAPHICS .INSERT HVG.LIB .INSERT MACRO.LIB .INSERT BBEQU.ASM .RELOC FR.P1=2 FR.P2=4 FR.P3=6 FR.P4=8 FR.P5=10 FR.P6=12 FR.P7=14 FR.P8=16 BX.X=10 BX.Y=8 BX.XS=6 BX.YS=4 BX.MOD=2 CLP.S=6 CLP.C=10 .DEFINE GETARG[NARGS,%RETPL]= [ MVI A,NARGS LXI H,%RETPL JMP GETART %RETPL: ] .DEFINE FRAME=[ PUSH Y LXI Y,0 DADY SP] .DEFINE UNFRAME=[ POP Y] PIXFUN:: TSTC '(',PIXDUD PUSH B RSTEXP PUSH H TSTCC COMMA,PIXDUD RSTEXP TSTC ')',PIXDUD POP B PUSH D MOV D,L MOV E,C CALL GPIXEL MOV L,A MVI H,0 POP D POP B RET ; PIXEL COMMAND ; ROUTINE TO INTERROGATE PIXEL GPIXEL: CALL R2ACLP MOV B,A MVI A,4 RC INR B MOV A,M ..SHFT: RLC RLC DJNZ ..SHFT ANI 3 RET ; GET PARAMETERS AND SHOVE THEM ON THE STACK ROUTINE ; IN A = # PARMS HL= WHERE TO RETURN TO GETART:: PUSH H PUSH PSW RSTEXP POP PSW ; NEED TO LOOK FOR COMMA? PUSH PSW DCR A JRZ ..NOC TSTCC COMMA,PIXDUD ..NOC: POP PSW XTHL DCR A JRNZ GETART PCHL PIXDUD: JMP QWHAT# ; POINT DRAW ROUTINE POINT:: GETARG 3 POP H MOV A,L POP H POP B PUSH D MOV D,L MOV E,C CALL POINTR POP D RSTFIN ; POINT ROUTINE ; A=MODE PARAMETER ; DE= Y,X COORDINATES ; HL=SMASHED POINTR: BIT 2,A ; OR OR XOR? JRNZ PRPLOP ; NO ; OR OR XOR - SET XPAND RLC RLC ANI 0FCH OUT XPAND BIT 5,A JRNZ ORPT XORPT: CALL R2ACLP RC ORI 0101000B JMPR ORJOIN ORPT: CALL R2ACLP RC ORI 0011000B ORJOIN: OUT MAGIC RES 6,H MVI M,80H RET PRPLOP: BIT 3,A JRNZ PRIORW PLOP: PUSH B PLOP1: OUT XPAND MVI A,00001000B OUT MAGIC STA 0FFFH LDA 4FFFH MOV B,A CALL R2ACLP JRC PLOPNG ORI 00001000B OUT MAGIC MVI A,10001100B OUT XPAND STA 0FFFH LDA 4FFFH MOV C,A MOV A,B XRA M ANA C XRA M MOV M,A PLOPNG: POP B RET ; PRIORITY PRIORW: PUSH B ANI 3 MOV C,A CALL GPIXEL CMP C ; COMPARE TO WHATS THERE JRNC PLOPNG MOV A,C JMPR PLOP1 ; TERSE CIRCLE COMMAND CIRCLE:: GETARG 4 FRAME PUSH D LXI H,1 ; XA=1 SHLD CIRXA# DCX H ; HL=0 MOV E,FR.P2(Y) ; DE=R MOV D,FR.P2+1(Y) PUSH D DCX D CALL CIRPNT ; DRAW AT 0,R XCHG CALL NEGHL XCHG CALL CIRPNT ; AND AT 0,-R POP H ; R IS IN HL DAD H DCX H SHLD CIRYA# DCX H ; DELTA=YA-1 SHLD CIRDEL# CLOOP: LHLD CIRDEL# ; D=DELTA*2 DAD H BIT 7,H ; IS D<0? JRNZ DMINUS ; YEP LDED CIRYA# ; NO, COMPUTE D=D-YA ANA A DSBC D BIT 7,H ; NOW IS D<0? JRNZ CBOTH ; YEP - DO BOTH MOVES LHLD CIRXA# ; NO XA=XA+2 INX H INX H SHLD CIRXA# XCHG LHLD CIRDEL# ; DELTA=DELTA-XA ANA A DSBC D JMPR DSTOR ; D < 0 CASE DMINUS: LDED CIRXA# ; D=D+XA DAD D BIT 7,H ; IF D<0 JRZ CBOTH ; BUMP BOTH LHLD CIRYA# ; ELSE YA=YA-2 DCX H DCX H SHLD CIRYA# XCHG LHLD CIRDEL# ; DELTA=DELTA+YA DAD D JMPR DSTOR ; INCREMENT BOTH CBOTH: LHLD CIRXA# ; XA=XA+2 INX H INX H SHLD CIRXA# XCHG LHLD CIRYA# ; YA=YA-2 DCX H DCX H SHLD CIRYA# LBCD CIRDEL# ; DELTA=DELTA+YA-XA DAD B ANA A DSBC D DSTOR: SHLD CIRDEL# LHLD CIRYA# DCX H ; IF NEG, 0 OR 1 DCX H BIT 7,H JRZ ..CYOK ; CLOSE TO DONE - DRAW LAST TWO POINTS LXI D,0 MOV L,FR.P2(Y) ; HL=R MOV H,FR.P2+1(Y) CALL CIRPNT ; AT R,0 CALL NEGHL CALL CIRPNT ; AND -R,0 ; WE ARE DONE POP D ; YES - GO HOME UNFRAME POP H POP H POP H POP H RSTFIN ..CYOK: ; SUBROUTINE TO DRAW 4 POINTS ; AT X,Y -X,Y -X,-Y AND X,-Y DRAW4: LHLD CIRYA# CALL DIV2HL PUSH H XCHG LHLD CIRXA# CALL DIV2HL CALL CIRPNT ; X,Y XCHG CALL NEGHL XCHG CALL CIRPNT CALL NEGHL ; -X CALL CIRPNT ; -X,-Y POP D ; -X,Y CALL CIRPNT JMP CLOOP CIRPNT: PUSH H PUSH D MOV C,FR.P4(Y) ; GET X TRANS FACTOR MOV B,FR.P4+1(Y) DAD B ; GROSS CLIP CHECK MOV A,L ; SIGN OF L TO CY RLC MOV A,H ACI 0 JRNZ ..CIRX XCHG MOV C,FR.P3(Y) ; Y TRIP MOV B,FR.P3+1(Y) DAD B MOV A,L RLC MOV A,H ACI 0 JRNZ ..CIRX MOV D,L MOV A,FR.P1(Y) CALL POINTR ..CIRX: POP D POP H RET DIV2HL: ANA A MOV A,H RAR MOV H,A MOV A,L RAR MOV L,A RET NEGHL: MOV A,H CMA MOV H,A MOV A,L CMA MOV L,A INX H RET ; SCROLL COMMAND ; BASIC LINK IN SCROLC:: CALL SCCLNK RSTFIN SCCLNK: GETARG 5 ; ENTRY FROM CHAR DISPLAY SCROLE:: FRAME PUSH D CALL CLIP JRC ..NOSC ; CONVERT X SIZE TO BYTES MOV A,BX.XS(Y) ADI 3 RRC RRC ANI 3FH MOV C,A ; WHICH DIRECTION? MOV A,BX.MOD(Y) ANA A JRZ ..NOSC LXI D,-40 MOV B,BX.YS(Y) MOV A,BX.Y(Y) JM ..MINU ; POSITIVE CASE LXI D,40 ADD B DCR A ..MINU: DCR B ; FUDGE Y SIZE JRZ ..NOSC ; SKIP IF WAS ONLY 1 PUSH D MOV D,A MOV E,BX.X(Y) CALL R2A POP D MOV A,BX.MOD(Y) CALL ABS ..SCR1: PUSH B PUSH H ..SCR2: PUSH B PUSH D MVI B,0 XCHG DAD D PUSH H LDIR POP H POP D POP B DJNZ ..SCR2 ..KILL: MVI M,0 INX H DCR C JRNZ ..KILL POP H POP B DCR A JRNZ ..SCR1 ..NOSC: POP D UNFRAME POP H POP H POP H POP H POP H RET SNAP:: GETARG 4 TSTCC COMMA,..SDUD CALL TSTVFF# PUSH H FRAME PUSH D CALL CLIP JRC ..NOSN PUSH X MOV A,BX.XS(Y) MOV L,BX.MOD(Y) MOV H,BX.MOD+1(Y) MOV M,A ; STUFF X SIZE OF PAT INX H MVI M,0 INX H ADI 3 RRC RRC ANI 3FH MOV E,A MOV D,BX.YS(Y) MOV M,D INX H MVI M,0 INX H PUSH H POP X PUSH D MOV E,BX.X(Y) MOV A,BX.Y(Y) ADD D DCR A MOV D,A CALL R2A PUSH H ; IY=SOURCE POINTER POP Y MOV C,A ; C=SHIFT AMOUNT POP D ; DE=SIZES JRZ ..EASY ; JUMP ON EASY CASE ; CASE OF FIRST PIXEL TO SNAP NOT BEING ON BYTE BOUNDARY ..HARD: PUSH D PUSH Y MOV H,0(Y) ; H=FIRST BYTE TO START ..HDBL: INX Y ; BUMP SOURCE MOV D,0(Y) ; D=NEXT GUY MOV L,D ; INTO L AS WELL MOV B,C ; REINIT SHIFT AMT ..HDSL: DAD H ; SHIFT OVER SA PIXELS DAD H DJNZ ..HDSL MOV 0(X),H ; STUFF TO DEST MOV H,D ; SETUP FOR NEXT ITERATION INX X DCR E JRNZ ..HDBL POP Y ; TO NEXT LINE LXI D,40 DADY D POP D DCR D JRNZ ..HARD JMPR ..SNPD ..SDUD: JMP QWHAT# ; FASTER LOOP FOR ZERO SHIFT AMOUNT CASE ..EASY: LXI B,40 ..EZLL: MOV A,E PUSH Y ..EZBL: MOV L,0(Y) MOV 0(X),L INX X INX Y DCR A JRNZ ..EZBL POP Y DADY B DCR D JRNZ ..EZLL ; ..SNPD: POP X ..NOSN: POP D UNFRAME POP H POP H POP H POP H POP H RSTFIN ; TERSE SHOW COMMAND SHOW:: GETARG 3 TSTCC COMMA,..SHWD CALL TSTVFF# JMPR ..SHOK ..SHWD: JMP QWHAT# ..SHOK: POP B MOV A,C ; SAVE MODE MVI B,0 MOV C,M PUSH B INX H INX H MOV C,M PUSH B PUSH D FRAME PUSH D PUSH H PUSH PSW PUSH H CALL CLIP POP H JRC ..NOSH MOV A,BX.YS(Y) CMP M ; DID Y SIZE SHRINKO? JRNZ ..NOSH ; YES MOV B,A ; NO DCX H ; TO X SIZE DCX H MOV A,BX.XS(Y) ; LOOKAT X SIZE CMP M JRNZ ..NOSH ADI 3 ; COMPUTE X SIZE IN BYTES RRC RRC ANI 3FH MOV C,A ; GET AND FIX COORDINATES MOV A,BX.Y(Y) ADD B ; FUDGE TO TOP OF BOX DCR A MOV D,A MOV E,BX.X(Y) CALL R2A MOV D,A POP PSW ; RESTORE MODE RLC RLC RLC RLC ANI 30H ORA D OUT MAGIC RES 6,H ; MAKE ADDRESS MAGIC POP D INX D ; MOVE PAST Y SIZE INX D XCHG ; HL=SOURCE, DE=DEST ; NORMAL? WRITE ..NWRT: XRA A PUSH B PUSH D MOV B,A LDIR STAX D POP D XCHG MVI C,BYTEPL DAD B XCHG POP B DJNZ ..NWRT JMPR ..OK ..NOSH: POP PSW POP PSW ..OK: POP D UNFRAME POP H POP H POP H POP H POP H RSTFIN ; BOX COMMAND BOXDRW:: CALL BOXLNK RSTFIN BOXLNK: GETARG 5 DOBOX:: FRAME PUSH D CALL CLIP ..SKPL: JRC ..SKIP ; ABORT IF TOTAL OFFSCREEN ; WE NOW HAVE REASONABLE STUFF ON OUR STACK ; LETS DEAL WITH MODE STUFF NOW MOV C,BX.MOD(Y) MOV A,C ; IS MODE ZERO? ANA A JRZ ..SKIP ; YEP - IGNORE ANI 4 ; ISOLATE WRITE MODE STA WRMODE# MOV A,C ; ISOLATE PIXEL NUMBER ANI 3 MOV C,A MVI B,0 ; LOOKUP BYTE OF THOSE GUYS LXI H,MSKTBL DAD B MOV A,M STA PIXVAL# ; NOW THE EXCITING BOX PAINTING STARTS MOV E,BX.XS(Y) ..BOXP: MOV A,E ANA A JRZ ..SKIP ; IS MOD(X,4)=1? MOV A,BX.X(Y) ANI 3 CPI 1 JRNZ ..MNZ ; YES - IS XS>4? MOV A,E CPI 4 JRC ..XSL4 ; YS IS >4 - SO PAINT A FULL STRIPE MVI C,0FFH ; DO WHOLE KIT AND KABOODLE CALL ..STRC MVI D,4 ; A=X ADDR SUBTRACTOR JMPR ..XSTF ..MNZ: DCR A ANI 3 MOV C,A MVI A,4 SUB C CMP E ; COMPARE TO XS JRC ..XSBG MOV A,E ; MOD IS BIGGER ..XSBG: MOV B,A ; B=MIN MOV D,A XRA A ; FORM BIT MASK ..BITF: RRC RRC ORI 11000000B DJNZ ..BITF MOV B,C ..DOSF: RRC RRC ANI 3FH DJNZ ..DOSF MOV C,A ; REMEMBERIZE CALL ..STRC ..XSTF: MOV A,D ADD BX.X(Y) ; UPDATE X COORDINATE MOV BX.X(Y),A MOV A,E ; AND PIXELS LEFT (XS) SUB D MOV E,A JMPR ..BOXP ; LOOP BACK FOR MORE ; PAINT A FINAL STRIPE ..XSL4: MOV B,A XRA A ..XSLA: RRC RRC ORI 11000000B DJNZ ..XSLA MOV C,A CALL ..STRC ..SKIP: POP D UNFRAME POP H POP H POP H POP H POP H RET ; LOOP TO PAINT A BOX STRIPE ; MASK TO USE PASSED IN C ..STRC: PUSH D MOV D,BX.Y(Y) MOV E,BX.X(Y) CALL R2A ; CONVERT COORDINATES LXI D,-40 ; NEGATIVE SCREEN INCREMENT MOV B,BX.YS(Y) ; B=Y SIZE LDA WRMODE# ; WHICH TIGHT LOOP TO USE? ANA A JRNZ ..PLOP ; WRITE MAGIC (XOR FOR NOW) ..XORL: LDA PIXVAL# ANA C XRA M MOV M,A DAD D DJNZ ..XORL POP D RET ; PLOP WRITE LOOP ..PLOP: LDA PIXVAL# XRA M ANA C XRA M MOV M,A DAD D DJNZ ..PLOP POP D BOXPUT:: RET ; CLIP BOTH COORDINATES ROUTINE CLIP: LHLD WINPTR# CALL CLIPPER RC PUSH Y DCX Y DCX Y LHLD WINPTR# INX H INX H INX H INX H CALL CLIPPER POP Y RET ; CLIP COORDINATE ROUTINE ; HL = PARM AREA START IN WINDOW TABLE ; IY POINTS TO STACK FRAME SUCH THAT ; SIZE IS 6 BYTES DOWN, COORDINATE 10 BYTES DOWN CLIPPER: MOV E,M ; GET UPPER LIMIT INX H MOV D,M INX H MOV C,M ; GET LOWER LIMIT INX H MOV B,M PUSH B MOV L,CLP.C(Y) ; HL=COORDINATE MOV H,CLP.C+1(Y) MOV C,CLP.S(Y) ; BC=SIZE MOV B,CLP.S+1(Y) CALL ..TSTB ; BARF IF <= 0 JRZ ..NODR DCX B CALL ..DVBC ; BC=BC DIVIDE 2 ANA A DSBC B ; HL=LOWER MOV CLP.C(Y),L ; STUFF BACK STUFF MOV CLP.C+1(Y),H XCHG ; TO DE CALL CPHLDE ; IS LOWER>UL? JRC ..NODR ; DONT DRAW XTHL CALL CPHLDE ; IS LOWER < LOWER LIMIT? JRC ..LOK PUSH H ; SAVE LOWER LIMIT XCHG ; HL=LOWER,DE=LL ANA A DSBC D ; HL=LOWER - LIMIT XCHG MOV L,CLP.S(Y) ; HL=SIZE MOV H,CLP.S+1(Y) DAD D MOV CLP.S(Y),L ; STORE BACK MOV CLP.S+1(Y),H CALL ..TSTH ; IF H<= 0 ABORT JRZ ..NOD1 POP H ; SET COORDINATE AT MOV CLP.C(Y),L ; LOWER LIMIT MOV CLP.C+1(Y),H ; DEAL WITH OTHER END ..LOK: XCHG ; DE=LOWER LIMIT MOV L,CLP.C(Y) ; HL=COORDINATE MOV H,CLP.C+1(Y) MOV C,CLP.S(Y) ; BC=SIZE MOV B,CLP.S+1(Y) CALL ..TSTB JRZ ..NODR DCX B DAD B ; ADD TO LOWER EDGE XCHG ; UPPER TO DE CALL CPHLDE ; CAN WE DRAW? POP H ; H=UL JRZ ..UOK ; JUMP IF ON EDGE JRNC ..NOD2 ; IF UPPER < LOWER LIMIT DONT CALL CPHLDE ; IS UPPER > UL? JRNC ..UOK ; NO PROB ANA A ; COMPUTE SIZE FUDGE DSBC D XCHG ; TO DE MOV L,CLP.S(Y) MOV H,CLP.S+1(Y) DAD D ; HL=NEW SIZE MOV CLP.S(Y),L MOV CLP.S+1(Y),H CALL ..TSTH ; IF HL<=0 ABORT JRZ ..NOD2 ..UOK: ANA A ; RETURN CARRY CLEAR RET ; FOR GOOD GUYS ..NOD1: POP H ; BAD GUY - CLEAN UP STACK ..NODR: POP H ..NOD2: STC ; CY FOR DONT DRAW RET ; TEST FOR BC BEING <= 0 ..TSTB: MOV A,B ANA A JM ..LESZ ORA C RET ..LESZ: XRA A RET ; SIMILAR ROUTINE FOR HL ..TSTH: MOV A,H ANA A JM ..LESZ ORA L RET ; DIVIDE BC BY 2 ..DVBC: ANA A MOV A,B RAR MOV B,A MOV A,C RAR MOV C,A RET ; ROUTINE TO COMPARE HL TO DE ; RETURNS CY SET FOR HLHL) ; CY CLEAR, ZERO SET IF HL=DE ; CY CLEAR, ZERO CLEAR IF HL>DE (OR DE=MX, SET M=MOD(M+MN,MX) SUB L MOV B,A ; INCREMENT BOTH DIRECTIONS LHLD INCRO# MOV A,D ; CONFUSE Y ADD H MOV D,A VECT3: MOV A,E ; THEN X ADD L MOV E,A JMPR VECT5 ; M + MN IS < MX, SET M = M + MN VECT4: MOV B,A ; INCREMENT ONLY MAX DIMENSION LHLD INCRO# MOV A,C ; C = DIRECTION FLAG RRC JRNC VECT3 ; 0=>X, SO GO DO IT MOV A,D ; Y CASE ADD H MOV D,A ; END OF LOOP VECT5: POP PSW DCR A JRNZ VECT2 RET ; SUBROUTINE TO COMPUTE DELTA AND INCREMENT FOR TWO COORDINATES CDELTA: PUSH H PUSH D MOV L,C CALL SGNEXT XCHG MOV L,B CALL SGNEXT XRA A DSBC D ORA H JRZ ..CD1 MOV C,A MOV A,L CMA INR A MOV B,A JMPR ..CD3 ..CD1: ORA L JRZ ..CD2 MVI A,1 ..CD2: MOV B,L MOV C,A ..CD3: POP D POP H RET ; SIGN EXTENSION SUBROUTINE SGNEXT: MVI H,0 MOV A,L ANA A RP DCR H RET ; ABSOLUTE VALUE ROUTINE ; THIS ROUTINE COMPUTES THE ABSOLUTE VALUE OF THE ARGUMENT ; PASSED IN A. THE RESULT IS RETURNED IN A. ABS: ANA A RP CMA INR A RET ; RELATIVE TO ABSOLUTE CONVERSION ROUTINE ; WITH CLIPPING AGAINST BOUNDARYS OF CURRENT WINDOW R2ACLP:: LHLD WINPTR# MOV A,E ; CHECK X UPPER CALL CMPM INX H INX H JRZ ..OKX JRNC ..BAD CALL CMPM ; CHECK X LOWER JRC ..BAD ..OKX: INX H INX H MOV A,D CALL CMPM ; CHECK Y UPPER JRZ R2A JRNC ..BAD INX H INX H CALL CMPM ; CHECK Y LOWER JRNC R2A ..BAD: STC RET ; NONCLIPPING ENTRY POINT R2A:: PUSH B MOV A,D CMA ADI 52 MOV L,A MVI H,0 DAD H DAD H DAD H MOV B,H MOV C,L DAD H DAD H DAD B MOV A,E ADI 79 RRC RRC ANI 3FH MOV C,A MVI B,0 DAD B SET 6,H MOV A,E DCR A ANI 3 POP B RET ; SPECIAL COMPARE ROUTINE FOR R2ACLP THAT REALLY WORKS ; THIS GUY COMPARES M WITH A CMPM: XRA M ; DO SIGNS DIFFER? JM ..REVR ; YEP - REVERSE IT XRA M ; UNDOIT CMP M ; AND COMPARE RET ..REVR: XRA M ; SAME SCAM CMP M CMC ; BUT ZORK THE CY RET .END