2023-11-16 18:19:54 -05:00

577 lines
10 KiB
Plaintext

PAGE
SBTTL "--- MACHINE-DEPENDENT ROUTINES: ATARI ---"
; ------------
; CLEAR SCREEN
; ------------
; CLEAR SCREEN TO WHITE IF [ARG1] NEGATIVE
; CLEAR SCREEN TO BLACK IF [ARG1] POSITIVE
GCLEAR: LDA #LOW SCREEN ; MAKE [I] POINT TO
STA I+LO ; THE 1ST BYTE OF
LDA #HIGH SCREEN ; SCREEN RAM
STA I+HI
LDX #30 ; # PAGES TO CLEAR
LDY #0 ; INIT LOOP INDEX
LDA ARG1+HI ; IF [ARG1]
BMI GCLSN ; NEGATIVE CLEAR TO WHITE
LDA #00
BEQ GCLS ; CLEAR SCREEN TO BLACK
GCLSN: LDA #$FF ; ELSE CLEAR TO WHITE
GCLS: STA (I),Y
INY
BNE GCLS
INC I+HI
DEX
BNE GCLS
RTS
; ------------------------
; TEXT (ATARI SCREEN CODE)
; ------------------------
ERRM: DB 41,110,116,101,114,110,97,108,0 ; INTERNAL
DB 37,114,114,111,114,0,3,0 ; ERROR #
ERRML EQU $-ERRM
ENDM: DB 37,46,36,0,47,38,0 ; END OF
DB 51,37,51,51,41,47,46 ; SESSION
ENDML EQU $-ENDM
; -----
; ERROR
; -----
; ENTRY: ERROR CODE IN [A]
GERROR: STA $00 ; SAVE ERROR CODE
JSR STATUS ; SET UP STATUS LINE
LDX #LOW ERRM ; GET LSB
LDA #HIGH ERRM ; AND MSB OF TEXT ADDRESS
LDY #ERRML ; AND ITS LENGTH
JSR PRINT ; PRINT "INTERNAL ERROR #"
LDA $00 ; RETRIEVE ERROR CODE
JSR HEX ; DISPLAY IT IN HEX
LDA #0
JSR CHAR ; PRINT A SPACE
JMP GOVER ; AND PRINT "GAME OVER"
; ----
; QUIT
; ----
GQUIT: JSR STATUS ; SET UP MESSAGE LINE
LDA #13
STA CURSOR ; CENTER TEXT
GOVER: LDX #LOW ENDM ; LSB AND
LDA #HIGH ENDM ; MSB OF TEXT ADDRESS
LDY #ENDML ; LENGTH
JSR PRINT ; PRINT "GAME OVER"
HOLD: LDA CONSOL ; WAIT FOR CONSOLE KEYPRESS
CMP #7
BEQ HOLD
LETGO: LDA CONSOL ; WAIT FOR KEY RELEASE
CMP #7
BNE LETGO
JMP COLD ; AND DO A COLDSTART
; -----------------
; CLEAR STATUS LINE
; -----------------
NEWLIN: LDX #79
LDA #0
NEWL0: STA TEXT,X
DEX
BPL NEWL0
RTS
; ------------------
; SET UP STATUS LINE
; ------------------
; FOR ERRORS & DEBUGGER
STATUS: JSR NEWLIN
LDA #0
STA CURSOR
LDX #LOW DL1 ; TELL THE D-LIST WHERE
LDA #HIGH DL1 ; TO START ITSELF
STX DLTOP+LO
STA DLTOP+HI
STX SDLSTL+LO ; ALSO TELL ANTIC
STA SDLSTL+HI ; WHERE TO FIND OUR LIST
RTS
; ----------------
; PRINT [A] IN HEX
; ----------------
; HEX CHARS IN ATARI SCREEN CODE
HCHARS: DB 16,17,18,19,20,21,22,23,24,25 ; 0-9
DB 33,34,35,36,37,38 ; A-F
HEX: PHA ; SAVE HERE
LSR A ; SHIFT TOP NIBBLE
LSR A ; INTO POSITION
LSR A
LSR A
JSR NIBBLE ; AND PRINT IT
PLA ; RETRIEVE BYTE
NIBBLE: AND #%00001111 ; ISOLATE BITS 3-0
TAX
LDA HCHARS,X
; FALL THROUGH ...
; -----------------
; PRINT CHAR IN [A]
; -----------------
CHAR: LDX CURSOR
STA TEXT,X
INC CURSOR
RTS
; ----------
; PRINT TEXT
; ----------
; ENTRY: TEXT ADDRESS IN [X/A] (LSB/MSB)
; TEXT LENGTH IN [Y]
PRINT: STX LINE+LO ; LSB OF ADDRESS
STA LINE+HI ; MSB OF ADDRESS
STY LEN ; LENGTH
LDY #0
LDX CURSOR
PR0: LDA (LINE),Y
STA TEXT,X
INX
INY
DEC LEN
BNE PR0
STX CURSOR
RTS
; ------
; MEMTOP
; ------
; EXIT: [A]=$A0 IF 48K, ELSE [A]=0
MEMTOP: LDA #0 ; CLEAR $A000
STA $A000
LDX $A000 ; CHECK THE VALUE
BNE EMPTY ; RETURN [A]=0 IF NON-ZERO
LDA #$A0 ; ELSE RETURN $A0
EMPTY: RTS
; ------
; RANDOM
; ------
; EXIT: RANDOM 16-BIT WORD IN [X/A]
DORAND: LDA RANDOM
NOP ; A PAUSE ...
LDX RANDOM
RTS
; ------------
; SIMPLE DELAY
; ------------
; ENTRY: NEGATIVE JIFFY COUNT IN [VALUE]
DELAY: LDA #0 ; WAIT A JIFFY
STA RTCLOK
DEL1: LDA RTCLOK
BEQ DEL1
INC VALUE+LO
BNE DELAY
INC VALUE+HI
BNE DELAY
BEQ MOVED ; GET A VALUE AND RETURN
; -----
; INPUT
; -----
GINPUT: LDA ARG1+LO ; MOVE [ARG1] INTO [VALUE]
STA VALUE+LO
LDA ARG1+HI
STA VALUE+HI
LDA NARGS ; IF THERE ARE 2 ARGS THEN DO THE TABLE
CMP #1 ; ITERATIONS
BEQ NOIT
JMP ITRATE ; YES VIRGINIA, A JUMP
NOIT: LDA VALUE+HI
BMI DELAY ; DO A SIMPLE DELAY
ORA VALUE+LO ; IF NON-ZERO,
BNE TICK ; ENTER SENSE LOOP
MOVED: JSR SENSE ; ELSE READ JUST ONCE
MOVED2: JMP PUTBYT ; ELSE RETURN [A]
; INPUT SENSE LOOP
TICK: JSR SENSE ; GET READING INTO [A]
CMP #%10001111 ; ANY INPUT?
BNE MOVED2 ; YES, RETURN IT
LDA #0 ; ELSE WAIT 1 JIFFY
STA RTCLOK
TICK1: LDA RTCLOK
BEQ TICK1
JSR DECVAL ; DECREMENT COUNT
LDA VALUE+LO
ORA VALUE+HI ; ZERO YET?
BNE TICK ; NO, LOOP BACK
BEQ MOVED ; RETURN
; -------------------------
; CHECK KEYBOARD & JOYSTICK
; -------------------------
; EXIT: INPUT STATUS IN [A]
SENSE: LDA #0
STA ATRACT ; KILL ATTRACT MODE
LDA CH ; READ THE KEYBOARD REGISTER
CMP #$FF ; KEY PRESSED YET?
BEQ STICK ; IF NOT, CHECK STICK
TAY ; ELSE SAVE KEYCODE HERE
LDX #$FF ; RESET THE
STX CH ; KEYBOARD REGISTER
AND #%11000000 ; SHIFT OR CTRL CHAR?
BNE STICK ; IGNORE IF SO
LDA ATASCI,Y ; GET ATASCII CODE INTO [A]
CMP #'a' ; CONVERT TO
BCC KEXIT ; UPPER CASE ALPHA
CMP #'z'+1 ; IF NECESSARY
BCS KEXIT
SEC
SBC #$20
KEXIT: AND #%01111111 ; MAKE SURE IT'S POSITIVE
RTS
; CHECK THE JOYSTICK
STICK: LDA STICK0
AND #%00001111 ; MASK GARBAGE
LDX STRIG0 ; ALSO CHECK TRIGGER
BNE STIKEX ; EXIT IF NOT PRESSED
ORA #%00010000 ; ELSE SET BIT 4
STIKEX: ORA #%10000000 ; NEGATIVE FOR STICK READING
RTS ; RETURN WITH CODE IN [A]
; ------------------------
; ATASCII CONVERSION TABLE
; ------------------------
ATASCI: DB $6C,$6A,$3B,$8A,$8B,$6B,$2B,$2A
DB $6F,$80,$70,$75,$9B,$69,$2D,$3D
DB $76,$80,$63,$8C,$8D,$62,$78,$7A
DB $34,$80,$33,$36,$1B,$35,$32,$31
DB $2C,$20,$2E,$6E,$80,$6D,$2F,$81
DB $72,$80,$65,$79,$7F,$74,$77,$71
DB $39,$80,$30,$37,$7E,$38,$3C,$3E
DB $66,$68,$64,$80,$82,$67,$73,$61
; --------------------
; DUMP BLOCK TO SCREEN
; --------------------
; ENTRY: BLOCK TO DUMP IN [BLOCK] (TOP BYTE IN [BLOCK+7])
; X-COORDINATE IN [X], Y-COORDINATE IN [A]
DUMP: STX TOX ; SAVE X-COORDINATE
ASL A ; MULTIPLY Y-COORD BY 8
ASL A ; TO GET MODE LINE (0-191)
ASL A
TAY ; USE AS INDEX
LDX #7 ; INIT BLOCK-FETCHING INDEX
DUMP0: LDA VLOWS,Y ; GET LSB OF LINE ADDR
CLC
ADC TOX ; ADD X-POS
STA TOADR+LO ; TO GET LSB OF SCREEN ADDR
LDA VHIGHS,Y ; GET MSB OF LINE ADDR
ADC #0
STA TOADR+HI ; FORM MSB OF SCREEN ADDR
LDA BLOCK,X ; GET BLOCK DATA
DB $8D ; 6502 "STA nnnn" INSTRUCTION
TOADR: DW $0000 ; SCREEN RAM ADDRESS
INY ; NEXT SCAN LINE
DEX ; DONE 8 BYTES YET?
BPL DUMP0 ; NO, FETCH MORE
RTS
; -----------------------------------------------
; DUMP BLOCK TO SCREEN WITH MASK
;
; IF THE MASK BIT IS 1 THEN THE SCREEN SHOWS THRU
; IF THE MASK BIT IS 0 THEN THE ICON IS DISPLAYED
; -----------------------------------------------
; ENTRY: BLOCK TO DUMP IN [BLOCK] (TOP BYTE IN [BLOCK+7])
; MASK IN [MASK]
; X-COORDINATE IN [X], Y-COORDINATE IN [A]
DMPMSK: STX TOX ; SAVE X-COORDINATE
ASL A ; MULTIPLY Y-COORD BY 8
ASL A ; TO GET MODE LINE (0-191)
ASL A
TAY ; USE AS INDEX
LDX #7 ; INIT BLOCK-FETCHING INDEX
DMSK0: LDA VLOWS,Y ; GET LSB OF LINE ADDR
CLC
ADC TOX ; ADD X-POS
STA TOADR2+LO+1 ; TO GET LSB OF SCREEN ADDR
STA TOADR3+LO+1
LDA VHIGHS,Y ; GET MSB OF LINE ADDR
ADC #0
STA TOADR2+HI+1 ; FORM MSB OF SCREEN ADDR
STA TOADR3+HI+1
TOADR2: LDA $FFFF ; DUMMY GET SCREEN BYTE
EOR BLOCK,X
AND MASK,X
EOR BLOCK,X
TOADR3: STA $FFFF ; DUMMY PUT BACK ON SCREEN
INY ; NEXT SCAN LINE
DEX ; DONE 8 BYTES YET?
BPL DMSK0 ; NO, FETCH MORE
RTS
; -----
; SOUND
; -----
; PLAY SOUND [ARG1] (1-127)
GSOUND: LDA ARG1+LO
BMI SNDERR ; RANGE ERROR!
CMP #SOUNDS+1
BCS SNDERR ; SOUND NOT DEFINED
SEC
SBC #1 ; ZERO-ALIGN
ASL A ; AND WORD-ALIGN
TAX ; THE SOUND ID INDEX
LDA STABLE+LO,X ; GET LSB OF EXECUTION ADDR
STA PLAY+LO
LDA STABLE+HI,X ; AND MSB
STA PLAY+HI
DB $4C ; 6502 "JMP" INSTRUCTION
PLAY: DW $0000 ; SOUND JUMP VECTOR
; *** ERROR #13: UNDEFINED SOUND ***
SNDERR: LDA #13
JMP GERROR
; -----
; COPY?
; -----
; IS THIS A LEGAL COPY OF THE DISK?
GCOPYP EQU PREDS
; -------
; VERIFY?
; -------
; ARE THE GAME AND IMAGE FILES INTACT?
; NOTE: THIS DOES NOT OBSERVE EXTRA BIT LOW
; BUT USES EXTRA BIT HIGH! Le
GVERP: LDA #0 ; CLEAR
STA J+LO ; ACCUM FOR CHECKSUM
STA J+HI
STA K+LO
STA DBLOCK ; START AT 1ST GAME SECTOR
STA VPCH ; START @ BYTE 0064
STA VPC0 ; USE AS HIGH BIT
LDA #64 ; 64 W/LOW BIT IN VPC0
STA VPCL
LDA GBEGIN+GLEN ; SET BYTE LENGTH
STA I+HI ; FOR GAME CHECK
LDA GBEGIN+GLEN+1 ; (LENGTH IN WORDS -
ASL A ; SO MULTIPLY BY 2
STA I+LO ; TO GET BYTES
ROL I+HI
ROL K+LO
JMP READIN ; READ 1ST PAGE IN
VSUM: LDA VPCL ; NEW PAGE?
BNE VSUM2 ; NO, CONTINUE
READIN: LDX #0 ; SET UP FOR GETDSK
STX DBTOP
STX DCNT
INX
STX DUNIT
LDA #$52 ; "READ"
STA DCOMND
LDA #HIGH BUFFER ; NO MOVE
STA DBUFF+HI
LDA DBLOCK
JSR GETGME
VSUM2: LDY VPCL ; GET THIS BYTE
LDA BUFFER,Y
INC VPCL ; SET FOR NEXT BYTE
BNE VSUM3
INC VPCH
BNE VSUM3
INC VPC0
VSUM3: CLC
ADC J+LO ; ADD IT TO ACCUM
STA J+LO
BCC VSUM0
INC J+HI
VSUM0: LDA VPCL ; CHECK IF ALL BYTES DONE
CMP I+LO
BNE VSUM
LDA VPCH
CMP I+HI
BNE VSUM
LDA VPC0
CMP K+LO
BNE VSUM ; AS WORD ALIGNED SIZE
LDA GBEGIN+GCHECK
CMP J+HI
BEQ VSUM4
JMP BADVER ; OOPS
VSUM4: LDA GBEGIN+GCHECK+1
CMP J+LO
BEQ IFILE
JMP BADVER
; GAME FILE OK, CHECK IMAGE FILE
IFILE: LDA #0
STA K+LO
LDA ICODE+LO ; FIND VIRTUAL IBEGIN
STA J+LO
LDA ICODE+HI
STA J+HI
LDY #ILEN ; OFFSET TO LENGTH
LDA (J),Y
STA I+HI ; SET I TO LENGTH
INY
LDA (J),Y
ASL A ; *2 AS WORD VALUE
STA I+LO
ROL I+HI
ROL K+LO
LDY #ICHECK ; GET CHECKSUM
LDA (J),Y ; WHILE IT'S EASY
STA CHKSUM+HI ; SAVE IT HERE
INY
LDA (J),Y
STA CHKSUM+LO
LDA #0 ; CLEAR FOR IMAGE FILE
STA J+LO
STA J+HI
STA VPCH
STA VPC0
STA DBLOCK ; SET TO START OF IMAGE SECTORS.
LDA #8
STA VPCL ; HEADER OF IMAGE FILE
JMP IRDIN
ISUM: LDA VPCL ; NEW PAGE?
BNE ISUM2 ; NO, CONTINUE
IRDIN: LDX #0 ; SET UP FOR GETDSK
STX DBTOP
STX DCNT
INX
STX DUNIT
LDA #$52 ; "READ"
STA DCOMND
LDA #HIGH BUFFER ; NO MOVE
STA DBUFF+HI
LDA DBLOCK
JSR GETIMG
ISUM2: LDY VPCL ; GET THIS BYTE
LDA BUFFER,Y
INC VPCL ; SET FOR NEXT BYTE
BNE ISUM3
INC VPCH
BNE ISUM3
INC VPC0
ISUM3: CLC
ADC J+LO ; ADD IT TO ACCUM
STA J+LO
BCC ISUM0
INC J+HI
ISUM0: LDA VPCL ; CHECK IF ALL BYTES DONE
CMP I+LO
BNE ISUM
LDA VPCH
CMP I+HI
BNE ISUM
LDA VPC0
CMP K+LO
BNE ISUM ; AS WORD ALIGNED SIZE
LDA CHKSUM+LO ; COMPARE TO SAVED CHECKSUM
CMP J+LO
BNE BADVER
LDA CHKSUM+HI
CMP J+HI
BNE BADVER
JMP PREDS ; SUCCESS!
BADVER: JMP PREDF
END