Files
erkyrath.infocom-zcode-terps/atari/io.dip
Andrew Plotkin b642da811e Initial commit.
2023-11-16 18:19:54 -05:00

605 lines
11 KiB
Plaintext

PAGE
SBTTL "--- I/O ROUTINES ---"
; -----
; SHOWN
; -----
; DISPLAY NEGATIVE ICON [ARG3] AT X=[ARG1], Y=[ARG2]
; IF [ARG4] IS GIVEN IT POINTS TO THE MASK TO BE USED
GSHOWN: LDA #$FF
STA NEGATE ; SET NEGATE FLAG
BNE SHOWI ; AND DO A "SHOWI"
; -----
; SHOWI
; -----
; DISPLAY ICON [ARG3] AT X=[ARG1], Y=[ARG2]
; IF [ARG4] IS GIVEN IT POINTS TO THE MASK TO BE USED
GSHOWI: LDA #0
STA NEGATE ; DISABLE NEGATE
; ****************NEW ROUTINE********************
SHOWI: LDA #0
STA MSKFLG ; DISABLE MASKING UNTIL FURTHER NOTICE
LDA NARGS
CMP #3
BEQ NOMASK ; DO THE NORMAL THING
LDX ARG4+LO ; GET MASK INFO
LDA ARG4+HI
JSR ISU ; THIS ENTRY INTO [ISETUP] WILL PUT
; THE DATA FOR ICON [ARG4] INTO
; IX2,IY2,IADR2 ETC.
; AND RETURN WITH DATA FROM ICON [ARG3]
; IN IX1,IY1 ETC.
; * NOTE IT WILL NOT DETECT DIFFERENT *
; * BLOCKSETS IT USES THE BSET FROM *
; * [ARG3] *
LDA IX1
CMP IX2 ; IF THE WIDTH AND HEIGHT ARE NOT
BNE DRAWEX ; DO NOTHING
LDA IY1
CMP IY2
BNE DRAWEX
LDA #$FF ; SET MASK FLAG
STA MSKFLG
BNE ITENT ; GOTO RIGHT PLACE
NOMASK: LDX ARG3+LO ; SET UP
LDA ARG3+HI ; BSET, ITERS, IX1, IY1, IADR1+LO, IADR1+HI
JSR GETI
ITENT: LDA #0
STA TOPCUT ; ZERO THIS
STA MUH ; THIS TOO
STA SIDCUT ; AND THIS
; STA MDYCUT ; AND THIS
STA MDXCUT ; AND THIS
LDX ARG2+LO ; ICON Y1 POS LO
LDA ARG2+HI
BEQ DRAWI1 ; ICON STARTS ON WINDOW PAGE (YPOS= 00 XX)
CMP #$FF
BNE DRAWEX ; ICON WILL NOT BE DISPLAYED
;STARTS ON PAGE BEFORE WINDOW PAGE
TXA ; PUT LO YPOS IN <A>
EOR #$FF ; C=1 FROM CMP #$FF
ADC WINDY1 ; FIND DISTANCE FROM ICON Y1-> WINDOW Y1
BCC DRAWI2
; FALL THRU DISTANCE > MAX SIZE OF 255
DRAWEX: RTS ; GENERAL PURPOUS EXIT FROM DRAW ICON
DRAWI3: LDA WINDY2 ; * [WINDY2] IS ONE GREATER THAN LAST *
SEC ; * LINE OF WINDOW TO DISPLAY *
SBC ARG2+LO ; * IF THIS MAKES A DIFFERANCE TAKE *
BCC DRAWEX ; AMOUNT TO CUT FROM ROWS DISPLAYED
CMP IY1 ; * THE SEC MIGHT FIX *
BCS DRAWI4
STA IY1 ; EXIT WHEN ICON STARTS BELOW WINDOW
BCC DRAWI4
; THE ABOVE SECTION OCCURS IF THE ICON STARTS INDSIDE THE WINDOW
; AND FINDS THE NUMBER ROWS TO DRAW
DRAWI1: SEC ; ICON ON ZERO PAGE
LDA WINDY1
SBC ARG2+LO ; FIND (WINDY1-ICONY1)
BCC DRAWI3 ; IF NEGATIVE ICON STARTS AFTER WINDOW Y1
DRAWI2: STA TOPCUT ; OTHERWISE CUT THIS AMOUNT FROM TOP OF ICON
DRAWI4: LDA IY1 ; HEIGHT OF ICON
SEC
SBC TOPCUT ; DO CUT
BEQ DRAWEX
BCC DRAWEX ; NO ICON LEFT TO DRAW. GOOD BYE
STA YDEX1 ; *** NEED TO USE OTHER NAME???? ***
SBC WINDH ; *(+-1) SET IN WINDSET (HEIGHT OF WINDOW)
BCC DRAWI5 ; ICON SMALLER THAN WINDOW (DISPLAY ALL)
LDA WINDH ; DISPLAY A WINDOWS WORTH OF ICON
STA YDEX1
; MULTIPLY TOPCUT AND ICON WIDTH, ADD TO ICON POINTER TO POINT
; AT FIRST DISPLAYED ROW BLOCK
DRAWI5: LDA TOPCUT ; * NOT NEEDED IF NOT CHANGED LATER *
STA MUSHFT ; * JUST USE TOPCUT *
CLC
ADC ARG2+LO ; CHANGE STARY YPOS OF ICON TO REFLECT
STA YPOS+LO ; TOPCUT
LDY #7 ; SHIFT COUNTER
LDX IX1 ; WIDTH COEFICIANT
DEX ; LESS ONE SO ADC C=0 SAME AS ADC C=1
DRAWI6: TXA ; GET IX1 BACK IN <A> FOR ADD
LSR MUSHFT ; SHIFT BIT 0 INTO <C>
BCC DRAWI7 ; C=0 SAME AS ADDING 0
ADC MUH
STA MUH ; ADD IXA TO TOTAL
DRAWI7: ROR MUH ; MUTIPLY BY 2
ROR MUL
DEY
BPL DRAWI6 ; DO 8 TIMES (8 BITS) GET IT?
; LDA IADR1+LO
; CLC
; ADC MUL ; ADD OFFSET INTO ICON
; STA IADR1+LO
; LDA IADR1+HI
; ADC MUH
; STA IADR1+HI
;***
LDA MUH
LDX MUL
JSR ADDIA1
LDA MSKFLG ; IF MASK ENABLED
BEQ NOMSK1
LDA MUH ; X IS STILL MUL
JSR ADDIA2
;***
; COMPUTE THE DISPLAYED WIDTH AND THE IXSKIP
NOMSK1: LDA IX1 ; KLUDGE
STA MDXCUT
LDX ARG1+LO ; ICON X CORDINATE
LDA ARG1+HI
BEQ DRAWI8 ; ICON STARTS ON WINDOW PAGE (XPOS= 00 XX)
CMP #$FF
BNE DRAWE2 ; ICON WILL NOT BE DISPLAYED
; STARTS ON PAGE BEFORE WINDOW PAGE
TXA ; PUT LO XPOS IN <A>
EOR #$FF ; C=1 FROM CMP #$FF
ADC WINDX1 ; FIND DISTANCE FROM ICON X1-> WINDOW X1
BCC DRAWI9
; FALL THRU DISTANCE > MAX ICON SIZE OF 255
DRAWE2: RTS ; AN EXIT FROM DRAW ICON
DRAWIA: LDA WINDX2 ; ICON STARTS INSIDE WINDOW
SEC
SBC ARG1+LO ; CHECK IF ICON STARTS TO RIGHT OF WINDOW
BCC DRAWE2 ; FOR LATER
CMP IX1
BCS DRAWIB
STA IX1 ; STARTS TO RIGHT DON T BOTHER
BCC DRAWIB
DRAWI8: LDA WINDX1 ; ICON STARTS ON ZERO PAGE
SEC
SBC ARG1+LO ; FIND (WINDX2-ICONX1)
BCC DRAWIA ; IF NEGATIVE ICON STARTS AFTER WINDOW X1
DRAWI9: STA SIDCUT ; OTHERWISE CUT THIS FROF LEFT OF ICON
DRAWIB: LDA IX1 ; WIDTH OF ICON
SEC
SBC SIDCUT ; DO CUT
BEQ DRAWE2
BCC DRAWE2 ; NO ICON TO DRAW BYE BYE
STA XDEX1
SBC WINDW ; IF ICON SMALLER THAN WINDOW DISPLAY ALL
BCC DRAWIC
LDA WINDW ; OTHERWISE DISPLAY WINDOW WIDTH OF ICON
STA XDEX1
;DRAWIC: LDA IADR1+LO
; CLC
; ADC SIDCUT
; STA IADR1+LO
; BCC DRAWID
; INC IADR1+HI
;***
DRAWIC: LDA #00
LDX SIDCUT
JSR ADDIA1
;***
LDA MSKFLG ; IS MASK ENABLED
BEQ DRAWID
LDA #00 ; X IS STILL SIDCUT
JSR ADDIA2
DRAWID: LDA MDXCUT
SEC
SBC XDEX1
STA IXSKIP
LDA XDEX1
STA IX1 ; SET THE COUNTER REFRESH VALUE
LDA ARG1+LO
CLC
ADC SIDCUT
STA XPOS+LO
STA XPSAV+LO
;**************************************
LDA BSET ; GET REQUIRED BLOCK SET INTO RAM
JSR GETBS
LDA MSKFLG ; IF ENABLED GO DO THE MASK THING
BNE DOMASK
; DRAW THE ICON ITERATION AT [IADR1]
DRAW: LDA IADR1+LO ; POINT [VPC] TO NEXT ICON BYTE
STA VPCL
LDA IADR1+HI
STA VPCH
;***
LDA IADR10
STA VPC0
;***
LDA #0
STA VPCFLG ; INVALIDATE [VPC]
JSR GETBYT ; GET BLOCK ID INTO [A]
JSR GETBLK ; GET BLOCK [A] INTO [BLOCK]
LDX XPOS+LO ; GET SCREEN COORDINATES
LDA YPOS+LO ; INTO [X] AND [A]
JSR DUMP ; DUMP [BLOCK] AT X=[X], Y=[A]
DEC XDEX1 ; DEC INDEX OF DISPLAYED WIDTH
BEQ CLPRI2 ; OUT OF COLUMNS: DO NEXT ROW
INC XPOS+LO ; INCREMENT X CORDINATE
;***
JSR INCIA1
;***
JMP DRAW
CLPRI2: LDA IX1 ; REFRESH
STA XDEX1 ; X-COUNT
LDA XPSAV+LO ; RESET X-POS
STA XPOS+LO
;***
LDA #0
LDX IXSKIP
JSR ADDIA1
JSR INCIA1
;***
INC YPOS+LO ; INCREMENT
DEC YDEX1 ; OUT OF Y'S YET?
BNE DRAW ; NO, KEEP DUMPING
RTS ; TILL EMPTY
; DRAW THE ICON ITERATION AT [IADR1] WITH MASK AT [IADR2]
DOMASK: LDA IADR2+LO ; POINT [VPC] TO NEXT MASK BYTE
STA VPCL
LDA IADR2+HI
STA VPCH
LDA IADR20
STA VPC0
LDA NEGATE ; SAVE NEGATE STATUS
PHA
LDA #00
STA VPCFLG ; INVAL FLAG
STA NEGATE ; NEVER NEGATE THE MASK
JSR GETBYT ; GET MASK BLOCK
JSR GETBLK ; GET MASK INTO [BLOCK]
JSR B2MASK ; COPY [BLOCK] INTO [MASK]
LDA IADR1+LO ; POINT [VPC] TO NEXT ICON BYTE
STA VPCL
LDA IADR1+HI
STA VPCH
LDA IADR10
STA VPC0
PLA ; RESTORE THE NEGATE
STA NEGATE
LDA #0
STA VPCFLG ; INVALIDATE [VPC]
JSR GETBYT ; GET BLOCK ID INTO [A]
JSR GETBLK ; GET BLOCK [A] INTO [BLOCK]
LDX XPOS+LO ; GET SCREEN COORDINATES
LDA YPOS+LO ; INTO [X] AND [A]
JSR DMPMSK ; DRAW [BLOCK] AGAINST [MASK] AT X=[X], Y=[A]
DEC XDEX1 ; DEC INDEX OF DISPLAYED WIDTH
BEQ CLPRIA ; OUT OF COLUMNS: DO NEXT ROW
INC XPOS+LO ; INCREMENT X CORDINATE
;***
JSR INCIA1
JSR INCIA2
;***
JMP DOMASK
CLPRIA: LDA IX1 ; REFRESH
STA XDEX1 ; X-COUNT
LDA XPSAV+LO ; RESET X-POS
STA XPOS+LO
;***
LDA #0
LDX IXSKIP
JSR ADDIA1
JSR INCIA1
LDA #0
JSR ADDIA2
JSR INCIA2
;***
INC YPOS+LO ; INCREMENT
DEC YDEX1 ; OUT OF Y'S YET?
BNE DOMASK ; NO, KEEP DUMPING
RTS ; TILL EMPTY
; ------
; B2MASK
; ------
B2MASK: LDX #7
B2MLP: LDA BLOCK,X
STA MASK,X
DEX
BPL B2MLP
RTS
; ----
; SETI
; ----
; COPY ICON [ARG3] INTO ICON [ARG4] WITH
; TOP LEFT CORNER AT X=[ARG1], Y=[ARG2];
; RETURN ZERO IF RANGE ERROR, ONE IF OKAY
GSETI: JSR ISETUP ; GET STATS OF SOURCE & DEST
JSR DOFIT ; WILL SOURCE FIT IN DEST?
BCC SI0 ; CARRY CLEAR IF OKAY
JMP RET0 ; ELSE RETURN A ZERO
; [IADR2] HAS ABS ADDR OF SUB-ICON
; [VPC] POINTS TO 1ST BYTE OF SOURCE ICON
SI0: LDA #0
STA I+LO ; INIT X-ROW POINTER
SI1: JSR GETBYT ; GET A BYTE FROM SOURCE
LDY I+LO
STA (IADR2),Y ; STORE IN DEST
INC I+LO ; UPDATE ROW POINTER
DEC XDEX1 ; OUT OF SOURCE X'S YET?
BNE SI1 ; NO, MOVE ANOTHER BYTE
LDA IX1 ; ELSE REFRESH
STA XDEX1 ; X-COUNT
LDA IX2 ; GET X-SIZE OF DEST
CLC
ADC IADR2+LO ; ADD TO BASE ADDR OF SUB-ICON
STA IADR2+LO ; TO GET ADDR OF NEXT SUB-ROW
BCC SI3
INC IADR2+HI
SI3: DEC YDEX1 ; OUT OF Y'S YET?
BNE SI0 ; RESET X-INDEX AND LOOP TILL EMPTY
LDA #1
JMP PUTBYT ; RETURN A 1 FOR SUCCESS
; -----
; SWAPI
; -----
; SAME AS "SETI" EXCEPT ICON [ARG4] SUB-DATA IS COPIED
; BACK INTO ICON [ARG3]
GSWAPI: JSR ISETUP
LDA IADR1+HI ; MAKE SURE SOURCE ICON
CMP IPURE ; IS IN I-PRELOAD
BCC GSW0 ; ERROR IF NOT
; *** ERROR #14: PURITY VIOLATION (SETI/SWAPI) ***
PRERR2: LDA #14
JMP GERROR
GSW0: JSR DOFIT ; WILL SOURCE FIT IN DEST?
BCC GSW1 ; CARRY CLEAR IF OKAY
JMP RET0 ; ELSE RETURN A ZERO
GSW1: LDA IADR1+HI ; MAKE [IADR1] ABSOLUTE
SEC
SBC ISTART ; STRIP OFF VIRTUAL OFFSET
;***
LSR IADR10
ROL IADR1+LO
ROL A
;***
CLC
ADC ICODE+HI ; ADD BASE ADDR OF I-PRELOAD
STA IADR1+HI ; LSB NEEDN'T CHANGE
GSW2: LDA #0 ; INIT ROW INDEX
STA I+LO
GSW3: LDY I+LO ; GET ROW INDEX
LDA (IADR1),Y ; GET BYTE FROM SOURCE ICON
STA I+HI ; SAVE IT HERE
LDA (IADR2),Y ; GET BYTE FROM DEST ICON
STA (IADR1),Y ; MOVE IT TO SOURCE ICON
LDA I+HI ; RETRIEVE SOURCE BYTE
STA (IADR2),Y ; AND MOVE IT TO DEST ICON
INC I+LO ; UPDATE ROW INDEX
DEC XDEX1 ; OUT OF X'S YET?
BNE GSW3 ; NO, KEEP LOOPING
LDA IX1 ; ELSE REFRESH X-COUNT
STA XDEX1
LDA IX2 ; ADD X-SIZE OF DEST
CLC ; TO BASE ADDR OF SUB-ICON
ADC IADR2+LO ; TO GET ADDR OF NEXT ROW
STA IADR2+LO
BCC GSW4
INC IADR2+HI
GSW4: LDA IX1 ; ADD X-SIZE OF SOURCE
CLC ; TO BASE ADDR OF SOURCE
ADC IADR1+LO ; TO GET ADDR OF NEXT ROW
STA IADR1+LO
BCC GSW5
INC IADR1+HI
GSW5: DEC YDEX1 ; OUT OF Y'S YET?
BNE GSW2 ; RESET ROW INDEX & LOOP TILL EMPTY
LDA #1
JMP PUTBYT ; RETURN A 1 FOR SUCCESS
; ------
; WINDOW
; ------
X1 EQU ARG1
Y1 EQU ARG2
X2 EQU ARG3
Y2 EQU ARG4
GWIND: LDY #6 ; SET INDEX TO DO ALL ARGS
WILP: LDX #0 ; TO ZERO ARGS LATER
LDA X1+HI,Y ; TEST IF - OR >255
BEQ WISK1 ; IF 0 DONT ADJUST GOTO NEXT ARG
BPL WISK2 ; IF PLUS ADJUST TO 255
STX X1+LO,Y ; CLIP FROM NEGATIVE TO ZERO
BMI WISK1 ; BRANCH
WISK2: DEX ; [X] = 255
STX X1+LO,Y ; IF > 255 CLIP TO 255
WISK1: DEY
DEY ; 2 DEYS FOR NEXT ARG (WORD)
BPL WILP ; DO Y2-X1
LDX #39 ; MAXIMUM X-VALUE
LDY #23 ; MAXIMUM Y-VALUE
LDA X1+LO ; CLIP X1
CMP #40
BCC WISK3
STX X1+LO
WISK3: LDA X2+LO ; CLIP X2
CMP #40
BCC WISK4
STX X2+LO
WISK4: LDA Y1+LO ; CLIP Y1
CMP #24
BCC WISK5
STY Y1+LO
WISK5: LDA Y2+LO ; CLIP Y2
CMP #24
BCC WISK6
STY Y2+LO
; SWITCH IF NEEDED
WISK6: LDX X1+LO
LDY X2+LO
CPX X2+LO ; IS X1 > X2?
BCS WISK7 ; BRANCH YES
STX WINDX1 ; SET X1 = X1
STY WINDX2 ; SET X2 = X2
BCC WISK8 ; BRANCH
WISK7: STX WINDX2 ; SWAP
STY WINDX1 ; X1 AND X2
WISK8: LDX Y1+LO ; GET Y1 AND
LDY Y2+LO ; Y2
CPX Y2+LO ; IS Y1 > Y2?
BCS WISK9 ; BRANCH YES
STX WINDY1 ; SET Y1 = Y1
STY WINDY2 ; SET Y2 = Y2
BCC WISKA ; BRANCH
WISK9: STX WINDY2 ; SWAP
STY WINDY1 ; Y1 AND Y2
WISKA: INC WINDX2 ; THIS IS SO A BCC WILL WORK ON CLIP
INC WINDY2 ; SAME
LDA WINDY2 ; COMPUTE HEIGHT
SEC
SBC WINDY1
STA WINDH
LDA WINDX2 ; COMPUTE WIDTH
SBC WINDX1 ; C=1 FROM ABOVE
STA WINDW
RTS
MULXY STY MUSHFT
LDY #7
LDA #0
STA MUH
TXA ; TEST 0
BEQ MU0
DEX
MULP1: TXA
LSR MUSHFT
BCC MUSK1
ADC MUH
STA MUH
MUSK1: ROR MUH
ROR MUL
DEY
BPL MULP1
RTS
MU0: STA MUL
RTS
END