Initial commit.

This commit is contained in:
Andrew Plotkin
2023-11-16 18:19:54 -05:00
commit b642da811e
796 changed files with 433816 additions and 0 deletions

BIN
atari/atari-d.zip Normal file

Binary file not shown.

BIN
atari/atari-grip.bin Normal file

Binary file not shown.

6289
atari/atari-grip.prn Normal file

File diff suppressed because it is too large Load Diff

6359
atari/atarizip-d.asm Normal file

File diff suppressed because it is too large Load Diff

193
atari/bugger.dip Normal file
View File

@@ -0,0 +1,193 @@
PAGE
SBTTL "--- ATARI DEBUGGER ---"
; -------------
; DEBUGGER INIT
; -------------
; BUG TITLES IN ATARI SCREEN CODE
BLINE: DB 34,48,26,0,0,0 ; BP:
DB 0,13,47,48,26,0,0,0 ; -OP:
DB 48,35,26,0,0,0,0,0,0 ; PC:
; DB 34,26,0,0,0 ; B:
DB 51,48,26,0,0,0 ; SP:
DB 54,45,26,0,0,0,0,0 ; VM:
DB 0,0,0
DB 17,26,0,0,0 ; 1:
DB 18,26,0,0,0 ; 2:
DB 19,26,0,0,0 ; 3:
DB 20,26,0,0,0 ; 4:
DB 21,26,0,0,0 ; 5:
DB 22,26,0,0,0 ; 6:
DB 23,26,0,0,0 ; 7:
DB 24,26,0,0,0 ; 8:
BLINEL EQU $-BLINE
BUGNIT: JSR STATUS ; SET UP STATUS LINE
LDX #LOW BLINE
LDA #HIGH BLINE
LDY #BLINEL
JMP PRINT
; --------
; DEBUGGER
; --------
; ENTRY: BREAKPOINT ID # IN [A]
DOBUG: LDX STRIG1
BNE BUGIT
RTS
BUGIT: LDX #3
STX CURSOR
JSR HEX ; SHOW BREAKPOINT ID
INC CURSOR ; POSITION FOR OPCODE ID
LDA OPCODE
BMI ITQ0
LDA #18 ; 2-OP
BNE SHOWOP
ITQ0: CMP #$B0
BCS ITQ1
LDA #17 ; 1-OP
BNE SHOWOP
ITQ1: CMP #$C0
BCS ITQ2
LDA #16 ; 0-OP
BNE SHOWOP
ITQ2: CMP #$E0
BCS ITQ3
LDA #37 ; EXTENDED 2-OP
BNE SHOWOP
ITQ3: LDA #56 ; X-OP
SHOWOP: JSR CHAR ; SHOW OPCODE ID
LDA #11
STA CURSOR ; POS FOR OPCODE BYTE
LDA OPCODE
JSR HEX ; SHOW IT
LDA #17
STA CURSOR ; POS FOR PC
LDA GPCH
JSR HEX ; SHOW MSB
LDA GPCL
JSR HEX ; AND LSB
LDA #$0B
LDX GPC0
BNE BGSKP1
LDA #$0D
BGSKP1: JSR CHAR
; LDA #24
; STA CURSOR ; POS FOR BYTE
; LDA MBYTE
; JSR HEX
LDA #26
STA CURSOR ; POS FOR SP
LDA GSP
JSR HEX ; SHOW SP
LDA #32
STA CURSOR ; POS FOR VM
LDA VPCH
JSR HEX ; SHOW MSB
LDA VPCL
JSR HEX ; AND LSB
LDA #$0B
LDX VPC0
BNE BGSK2
LDA #$0D
BGSK2: JSR CHAR
; DISPLAY BYTES 1 THRU 8
LDA #42
STA CURSOR
LDA BYTE1
JSR HEX
LDA #47
STA CURSOR
LDA BYTE2
JSR HEX
LDA #52
STA CURSOR
LDA BYTE3
JSR HEX
LDA #57
STA CURSOR
LDA BYTE4
JSR HEX
LDA #62
STA CURSOR
LDA BYTE5
JSR HEX
LDA #67
STA CURSOR
LDA BYTE6
JSR HEX
LDA #72
STA CURSOR
LDA BYTE7
JSR HEX
LDA #77
STA CURSOR
LDA BYTE8
JSR HEX
WAIT: LDA CONSOL
CMP #7
BEQ WAIT
LETGO2: LDA CONSOL
CMP #7
BNE LETGO2
LDA #0 ; 1/2 SECOND DELAY
STA RTCLOK
ZZZ: LDA RTCLOK
CMP #30
BCC ZZZ
BUGEX: LDA #00
LDX #7
BGLP: STA BYTE1,X
DEX
BPL BGLP
RTS
MBYTE: DB 0 ; SAVE BYTE
BYTE1: DB 00 ; USER BYTE1
BYTE2: DB 00
BYTE3: DB 00
BYTE4: DB 00
BYTE5: DB 00
BYTE6: DB 00
BYTE7: DB 00
BYTE8: DB 00
END

124
atari/bugger.src Normal file
View File

@@ -0,0 +1,124 @@
PAGE
SBTTL "--- DEBUGGER: CBM64 ---"
; --------------
; CBM64 DEBUGGER
; --------------
; ENTRY: BREAKPOINT ID IN [A]
BLINE: DB "B: OP: PC: B: S: V:"
BLINL EQU $-BLINE
BUGLIN EQU SCREEN+40
DOBUG: LDX CONSOL ; CHECK CONSOLE
CPX #5 ; "SELECT" PRESSED?
BNE BUGIT ; IF SO,
RTS ; EXIT
BUGIT: PHA ; ELSE SAVE BREAK ID
LDX #39
DBG0: LDA #0
STA BUGLIN,X ; CLEAR SCREEN LINE
DEX
BPL DBG0
LDX #0
DBG1: LDA BLINE,X ; PRINT DEBUGGER TEXT
STA BUGLIN,X
INX
CPX #BLINL
BCC DBG1
LDX #2 ; INIT "CURSOR"
PLA
JSR HEX ; SHOW BREAKPOINT
LDA OPCODE
BMI ITQ0
LDA #'2'
BNE SHOWOP
ITQ0: CMP #$B0
BCS ITQ1
LDA #'1'
BNE SHOWOP
ITQ1: CMP #$C0
BCS ITQ2
LDA #'0'
BNE SHOWOP
ITQ2: CMP #$E0
BCS ITQ3
LDA #'E'
BNE SHOWOP
ITQ3: LDA #'X'
SHOWOP: LDX #5 ; SET CURSOR
STA BUGLIN,X
LDX #9 ; CURSOR FOR OP ID
LDA OPCODE
JSR HEX
LDX #15 ; CURSOR FOR PC
LDA ZPCH
JSR HEX
LDA ZPCM
JSR HEX
LDA ZPCL
JSR HEX
LDX #24 ; CURSOR FOR BYTE
LDA MBYTE
JSR HEX
LDX #29 ; CURSOR FOR [ZSP]
LDA ZSP
JSR HEX
LDX #34 ; CURSOR FOR [MPC]
LDA MPCH
JSR HEX
LDA MPCM
JSR HEX
LDA MPCL
JSR HEX
LDA CONSOL
CMP #6 ; "START" PRESSED?
BNE LETEX ; EXIT IF NOT
LETGO: LDA CONSOL ; ELSE WAIT FOR
CMP #6 ; "START" TO BE RELEASED
BEQ LETGO
LETEX: RTS
; CONVERT [A] TO HEX & PRINT
HEX: PHA
LSR A
LSR A
LSR A
LSR A
JSR NIB
PLA
NIB: AND #%00001111
TAY
LDA HCHARS,Y
STA BUGLIN,X
INX
RTS
HCHARS: DB "0123456789ABCDEF"
MBYTE: DB 0
END

161
atari/cold.dip Normal file
View File

@@ -0,0 +1,161 @@
PAGE
SBTTL "--- MACHINE COLDSTART: ATARI ---"
ORG GRIP
; -----------------
; ATARI BOOT HEADER
; -----------------
DB 0 ; FLAG BYTE (IGNORED)
DB 53 ; LOAD ALL OF TRACKS 0, 1 AND 2
DW GRIP ; WHERE TO LOAD THE SECTORS
DW DUMMY ; POINT TO INIT SUBROUTINE
; --------------
; BOOT COLDSTART
; --------------
LDA #LOW COLD ; POINT [DOSVEC] TO
STA DOSVEC+LO ; THE COLDSTART ROUTINE
LDA #HIGH COLD
STA DOSVEC+HI
DUMMY: LDA #$FF ; DISABLE BASIC ROM
STA PORTB ; IN XL-SERIES MACHINES
CLC ; SUCCESS FLAG
RTS
; -------------
; DISPLAY LISTS
; -------------
; LIST 1: SCREEN W/STATUS LINE
DL1: DB $70,$70,$60 ; 23 BLANK LINES
DB $42 ; TEXT LINE W/LMS
DW TEXT ; ADDRESS OF TEXT LINE
DB $02 ; A SECOND LINE OF TEXT
DB $01 ; JUMP INSTRUCTION
DW DL2A ; INTO DL2
; LIST 2: SCREEN W/O STATUS LINE (NORMAL)
DL2: DB $70,$70,$70 ; 24 BLANK LINES
DB $4F ; 1 SCAN LINE W/LMS
DW SCREEN ; ADDRESS OF SCREEN RAM
DB $0F,$0F,$0F,$0F ; 7 MORE
DB $0F,$0F,$0F ; SCAN LINES (0)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (2)
DL2A: DB $4F ; 1 SCAN LINE W/LMS
DW SCREEN+640 ; ADDRESS OF 8TH SCAN LINE
DB $0F,$0F,$0F,$0F ; 7 MORE
DB $0F,$0F,$0F ; SCAN LINES (1)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (3)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (4)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (5)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (6)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (7)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (8)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (9)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (10)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (11)
DB $4F ; 1 SCAN LINE W/LMS
DW SCREEN+3840 ; ADDRESS OF 96TH SCAN LINE
DB $0F,$0F,$0F,$0F ; 7 MORE
DB $0F,$0F,$0F ; SCAN LINES (12)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (13)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (14)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (15)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (16)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (17)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (18)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (19)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (20)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (21)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (22)
DB $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; (23)
DB $41 ; JUMP ON VERTICAL BLANK
DLTOP: DW DL2 ; TO TOP OF D-LIST 2
; ---------
; COLDSTART
; ---------
COLD: CLD
LDX #$FF ; RESET THE
TXS ; HARDWARE STACK
STX CH ; AND KEYBOARD REGISTER
STX PORTB ; REMOVE BASIC ROM IN XL-SERIES MACHINES
INX ; = 0
STX DMACTL ; SHUT OFF
STX SDMCTL ; ANTIC
STX COLOR2 ; BLACK BACKGROUND
STX COLDST ; COLDSTART OKAY
STX AUDCTL ; CLEAR SOUND
STX SOUNDR ; PREVENT I/O BEEPS
INX ; = 1
STX BOOT ; BOOT SUCCESSFUL
LDA #3
STA SKCTL ; RESET SOUND
LDA #$70
STA POKMSK ; DISABLE
STA IRQEN ; THE BREAK KEY
LDA #14 ; WHITE
STA COLOR1 ; GRAPHICS
; SET UP THE PLOT TABLES
LDA #LOW SCREEN ; ADDRESS OF SCAN LINE 0
STA VLOWS ; HARD-WIRE THE 1ST POSITION
STA I+LO ; ALSO INIT INDEX
LDA #HIGH SCREEN ; SAME FOR MSBS
STA VHIGHS
STA I+HI
LDX #1 ; START AT LINE 1
PTCALC: LDA I+LO
CLC
ADC #40
STA I+LO
STA VLOWS,X
LDA I+HI
ADC #0
STA I+HI
STA VHIGHS,X
INX
CPX #192
BNE PTCALC
LDA #$7F
STA ARG1+LO
STA ARG1+HI
JSR GCLEAR ; CLEAR SCREEN TO BLACK
IF DEBUG
JSR BUGNIT ; SET UP DEBUGGER
ELSE
LDA #LOW DL2 ; ELSE USE FULL-SCREEN
STA SDLSTL+LO
STA DLTOP+LO
LDA #HIGH DL2
STA SDLSTL+HI
STA DLTOP+HI
ENDIF
LDA #$22
STA SDMCTL ; RESTORE ANTIC
; FALL THROUGH TO WARMSTART ...
END

125
atari/cold.src Normal file
View File

@@ -0,0 +1,125 @@
PAGE
SBTTL "--- MACHINE COLDSTART: ATARI ---"
ORG ZIP
; -----------------
; ATARI BOOT HEADER
; -----------------
DB 0 ; FLAG BYTE (IGNORED)
DB 56 ; LOAD 7K OF CODE
DW ZIP ; WHERE TO LOAD THE SECTORS
DW DUMMY ; POINT TO INIT SUBROUTINE
; --------------
; BOOT COLDSTART
; --------------
LDA #LOW COLD ; POINT [DOSVEC] TO
STA DOSVEC+LO ; THE COLDSTART ROUTINE
LDA #HIGH COLD
STA DOSVEC+HI
DUMMY: LDA #$FF ; DISABLE BASIC ROM
STA PORTB ; IN XL-SERIES MACHINES
CLC ; SUCCESS FLAG
RTS
; -------------------
; CUSTOM DISPLAY LIST
; -------------------
DLIST: DB $70,$70,$50 ; 22 BLANK LINES
DB $42 ; 1 TEXT LINE W/LMS
DW SCREEN ; ADDR OF SCREEN RAM
DB $10 ; 2 BLANK LINES
DB $02,$02,$02,$02,$02,$02,$02 ; 7 TEXT LINES
DB $02,$02,$02,$02,$02,$02,$02,$02 ; 8 TEXT LINES
DB $02,$02,$02,$02,$02,$02,$02,$02 ; 8 TEXT LINES
DB $41 ; JVB
DW DLIST ; ADDR OF D-LIST
SLD: DB "The story is loading ..."
DB EOL
SLDL EQU $-SLD
; ---------
; COLDSTART
; ---------
COLD: CLD
LDX #$FF ; RESET THE
TXS ; HARDWARE STACK
STX CH ; AND KEYBOARD REGISTER
STX PORTB ; REMOVE BASIC ROM IN XL MACHINES
INX ; = 0
STX COLDST ; COLDSTART OKAY
STX AUDCTL ; CLEAR SOUND
STX LMARGN ; NO LEFT MARGIN
STX SCRIPT ; DISABLE SCRIPTING
STX SFLAG ; DISABLE PREVIOS SCRIPT (BM 5/14/85)
INX ; = 1
STX BOOT ; BOOT SUCCESSFUL
STX GPRIOR ; MAXIMUM PMG PRIORITY
STX CRSINH ; INHIBIT OS CURSOR
LDA #3
STA SKCTL ; RESET SOUND
STA GRACTL ; ENABLE PLAYERS & MISSILES
LDA #$70
STA POKMSK ; DISABLE
STA IRQEN ; THE BREAK KEY
LDA #12 ; WHITE
STA COLOR1 ; TEXT
LDA #148
STA COLOR4 ; BLUE BORDER
LDX #$11 ; CLEAR ALL PMG REGISTERS
LDA #0
PMG0: STA HPOSP0,X
DEX
BPL PMG0
TAX ; [X] & [A] = 0
PMG1: STA MISSL,X ; CLEAR CURSOR RAM
INX
BNE PMG1
LDA #1 ; DOUBLE-WIDTH FOR
STA SIZEM ; MISSILE #0
LDA #HIGH PLMRAM ; POINT TO LOCATION
STA PMBASE ; OF PMG RAM
LDA #LOW DLIST ; ENABLE
STA SDLSTL+LO ; CUSTOM
LDA #HIGH DLIST ; DISPLAY
STA SDLSTL+HI ; LIST
; FALL THROUGH ...
; ---------------
; WARMSTART ENTRY
; ---------------
WARM: JSR CLS ; CLEAR SCREEN
LDA #8 ; POSITION CURSOR
STA COLCRS+LO ; AT (8,0)
LDA #0
STA ROWCRS
LDX #LOW SLD
LDA #HIGH SLD
LDY #SLDL
JSR SROOM ; "THE STORY IS LOADING ..."
LDA #%00111110 ; ENABLE 1-LINE PMG, STANDARD FIELD
STA SDMCTL ; RESTORE ANTIC
; FALL THROUGH TO ZIP WARMSTART ...
END

179
atari/disk.src Normal file
View File

@@ -0,0 +1,179 @@
PAGE
SBTTL "--- DISK ACCESS: ATARI ---"
; --------------------
; READ A VIRTUAL BLOCK
; --------------------
; ENTRY: TARGET V-BLOCK IN [DBLOCK]
; TARGET RAM PAGE IN [DBUFF]
; EXIT: CARRY CLEAR IF OKAY, SET IF NOT
GETDSK: CLD
LDA #1 ; V-BLOCKS ALWAYS COME
STA DRIVE ; FROM DRIVE #1
; CALCULATE SECTOR OF [DBLOCK]
LDX DBLOCK+LO ; COPY LSB OF [DBLOCK]
STX SECTOR+LO ; INTO [SECTOR]
LDA DBLOCK+HI
AND #%00000001 ; MASK ALL BUT BIT 1
STA SECTOR+HI
BNE INPURE ; BLOCK IS PURE IF MSB <> 0
CPX ZPURE ; ELSE CHECK LSB
BCS INPURE ; PURE IF >= [ZPURE]
; HANDLE A PRELOAD BLOCK
ASL SECTOR+LO ; MULTIPLY BY 2
ROL SECTOR+HI ; FOR ATARI 128-BYTE SECTORS
LDA SECTOR+LO
CLC
ADC #73 ; ADD DISK PRELOAD OFFSET
STA SECTOR+LO
BCC RDISK
INC SECTOR+HI
BNE RDISK ; AND READ THE SECTOR
; HANDLE A PURE BLOCK
INPURE: LDA SECTOR+LO
SEC ; STRIP OFF THE
SBC ZPURE ; VIRTUAL PRELOAD OFFSET
STA SECTOR+LO
BCS INP0
DEC SECTOR+HI
INP0: ASL SECTOR+LO ; MULTIPLY BY 2
ROL SECTOR+HI ; FOR ATARI 128-BYTE SECTORS
INC SECTOR+LO ; DISK "PURE" OFFSET IS 1
BNE RDISK
INC SECTOR+HI
; FALL THROUGH ...
; -----------------
; READ A DISK BLOCK
; -----------------
; ENTRY: TARGET SECTOR IN [SECTOR]
; TARGET DRIVE IN [DRIVE]
; PAGE TO READ IN [DBUFF]
; EXIT: CARRY CLEAR IF OKAY, SET IF NOT
RDISK: LDA #$52 ; "READ" COMMAND
JSR DODISK ; GET DATA INTO [IOBUFF]
BCS IOERR ; SOMETHING WRONG IF CARRY SET
LDY #0 ; MOVE DATA IN [IOBUFF]
RDSK0: LDA IOBUFF,Y ; TO [DBUFF]
STA (DBUFF),Y
INY
BNE RDSK0
BEQ SNEXT ; UPDATE & RETURN
; ------------------
; WRITE A DISK BLOCK
; ------------------
; ENTRY: TARGET SECTOR IN [SECTOR]
; TARGET DRIVE IN [DRIVE]
; PAGE TO WRITE IN [DBUFF]
; EXIT: CARRY CLEAR IF OKAY, SET IF NOT
PUTDSK: LDY #0 ; MOVE THE PAGE
PDSK0: LDA (DBUFF),Y ; AT [DBUFF]
STA IOBUFF,Y ; INTO [IOBUFF]
INY
BNE PDSK0
LDA #$57 ; "WRITE" COMMAND
JSR DODISK
BCS IOERR ; SOMETHING WRONG IF CARRY SET
SNEXT: INC DBUFF+HI ; POINT TO NEXT RAM PAGE
INC DBLOCK+LO ; NEXT V-PAGE
BNE SNX0
INC DBLOCK+HI
SNX0: INC SECTOR+LO ; AND NEXT SECTOR
BNE SNX1
INC SECTOR+HI
SNX1: CLC ; CLEAR CARRY FOR SUCCESS
IOERR: RTS ; ELSE RETURN WITH CARRY SET
; ---------------
; ACCESS THE DISK
; ---------------
; ENTRY: [A] = $52 TO READ, $57 TO WRITE
; [DRIVE] = TARGET DRIVE (1 OR 2)
; [SECTOR] = TARGET SECTOR
; EXIT: CARRY CLEAR IF OKAY, SET IF NOT
DODISK: STA DCOMND ; SET READ/WRITE COMMAND
LDA DRIVE ; SPECIFY
STA DUNIT ; WHICH DRIVE TO USE
; CHECK VALIDITY OF SECTOR RANGE
LDX SECTOR+LO ; GET LSB AND
LDA SECTOR+HI ; MSB OF TARGET SECTOR
CMP #$02 ; MSB WITHIN RANGE?
BCC RANOK ; OKAY IF < 2
BNE RANERR ; RANGE ERROR IF > 2
CPX #$D0 ; IF MSB WAS $02, IS LSB < $CF?
BCS RANERR ; ERROR IF NOT
RANOK: STX DAUX1 ; TELL SIO
STA DAUX2 ; WHICH SECTOR TO USE
LDA #LOW IOBUFF ; POINT TO
STA DBUFLO ; THE BOTTOM HALF
LDA #HIGH IOBUFF ; OF [IOBUFF]
STA DBUFHI
JSR DSKINV ; ACCESS 1ST HALF OF [IOBUFF]
LDA DSTATS ; CHECK STATUS
BMI DERR ; ERROR IF NEGATIVE
INC SECTOR+LO ; POINT TO NEXT SECTOR
BNE DDSK0
INC SECTOR+HI
DDSK0: LDA SECTOR+LO ; UPDATE [DAUX1/2]
STA DAUX1
LDA SECTOR+HI
STA DAUX2
LDA #LOW BUFTOP ; POINT TO TOP HALF
STA DBUFLO ; OF [IOBUFF]
LDA #HIGH BUFTOP
STA DBUFHI
JSR DSKINV ; ACCESS TOP HALF OF [IOBUFF]
LDA DSTATS ; CHECK STATUS
BMI DERR ; ERROR IF NEGATIVE
CLC ; CLEAR CARRY FOR NO ERRORS
RTS
DERR: SEC ; OR SET IT IF ERROR
RTS
; *** ERROR #12: DISK ADDRESS OUT OF RANGE ***
RANERR: LDA #12
JMP ZERROR
END

85
atari/dispatch.dip Normal file
View File

@@ -0,0 +1,85 @@
PAGE
SBTTL "--- OPCODE DISPATCH TABLES ---"
; -------------------
; 0-OP DISPATCH TABLE
; -------------------
OPT0: DW GNOOP ; 0
DW GRTRUE ; 1
DW GRFALS ; 2
DW GRSTAK ; 3
DW GFSTAK ; 4
DW GQUIT ; 5
DW GCOPYP ; 6
DW GVERP ; 7
NOPS0 EQU 8 ; # VALID 0-OPS
; -------------------
; 1-OP DISPATCH TABLE
; -------------------
OPT1: DW GPUSH ; 0
DW GPOP ; 1
DW GVALUE ; 2
DW GINC ; 3
DW GDEC ; 4
DW GZEROP ; 5
DW GBNOT ; 6
DW GJUMP ; 7
DW GRET ; 8
NOPS1 EQU 9 ; # VALID 1-OPS
; -------------------
; 2-OP DISPATCH TABLE
; -------------------
OPT2: DW BADOP2 ; 0, UNDEFINED
DW GADD ; 1
DW GSUB ; 2
DW GMUL ; 3
DW GDIV ; 4
DW GMOD ; 5
DW GBAND ; 6
DW GBIOR ; 7
DW GBXOR ; 8
DW GBITSP ; 9
DW GEQP ; 10
DW GLESSP ; 11
DW GDLESP ; 12
DW GGRTRP ; 13
DW GIGRTP ; 14
DW GSET ; 15
DW GGET ; 16
DW GGETB ; 17
NOPS2 EQU 18 ; # VALID 2-OPS
; -------------------
; X-OP DISPATCH TABLE
; -------------------
OPTX: DW GCALL ; 0
DW GPUT ; 1
DW GPUTB ; 2
DW GINPUT ; 3
DW GSHOWI ; 4
DW GSETI ; 5
DW GSWAPI ; 6
DW GSOUND ; 7
DW GRAND ; 8
DW GCLEAR ; 9
DW GSHOWN ; 10
DW GWIND ; 11
DW GITER ; 12
DW GLOAD ; 13
DW GDUMP ; 14
DW GREST ; 15
DW GSAVE ; 16
NOPSX EQU 17 ; # VALID X-OPS
END

92
atari/dispatch.src Normal file
View File

@@ -0,0 +1,92 @@
PAGE
SBTTL "--- OPCODE DISPATCH TABLES ---"
; 0-OPS
OPT0: DW ZRTRUE ; 0
DW ZRFALS ; 1
DW ZPRI ; 2
DW ZPRR ; 3
DW ZNOOP ; 4
DW ZSAVE ; 5
DW ZREST ; 6
DW ZSTART ; 7
DW ZRSTAK ; 8
DW POPVAL ; 9
DW ZQUIT ; 10
DW ZCRLF ; 11
DW ZUSL ; 12
DW ZVER ; 13
NOPS0 EQU 14 ; NUMBER OF 0-OPS
; 1-OPS
OPT1: DW ZZERO ; 0
DW ZNEXT ; 1
DW ZFIRST ; 2
DW ZLOC ; 3
DW ZPTSIZ ; 4
DW ZINC ; 5
DW ZDEC ; 6
DW ZPRB ; 7
DW BADOP1 ; 8 (UNDEFINED)
DW ZREMOV ; 9
DW ZPRD ; 10
DW ZRET ; 11
DW ZJUMP ; 12
DW ZPRINT ; 13
DW ZVALUE ; 14
DW ZBCOM ; 15
NOPS1 EQU 16 ; NUMBER OF 1-OPS
; 2-OPS
OPT2: DW BADOP2 ; 0 (UNDEFINED)
DW ZEQUAL ; 1
DW ZLESS ; 2
DW ZGRTR ; 3
DW ZDLESS ; 4
DW ZIGRTR ; 5
DW ZIN ; 6
DW ZBTST ; 7
DW ZBOR ; 8
DW ZBAND ; 9
DW ZFSETP ; 10
DW ZFSET ; 11
DW ZFCLR ; 12
DW ZSET ; 13
DW ZMOVE ; 14
DW ZGET ; 15
DW ZGETB ; 16
DW ZGETP ; 17
DW ZGETPT ; 18
DW ZNEXTP ; 19
DW ZADD ; 20
DW ZSUB ; 21
DW ZMUL ; 22
DW ZDIV ; 23
DW ZMOD ; 24
NOPS2 EQU 25 ; NUMBER OF 2-OPS
; X-OPS
OPTX: DW ZCALL ; 0
DW ZPUT ; 1
DW ZPUTB ; 2
DW ZPUTP ; 3
DW ZREAD ; 4
DW ZPRC ; 5
DW ZPRN ; 6
DW ZRAND ; 7
DW ZPUSH ; 8
DW ZPOP ; 9
DW ZSPLIT ; 10
DW ZSCRN ; 11
NOPSX EQU 12 ; NUMBER OF X-OPS
END

200
atari/eq.dip Normal file
View File

@@ -0,0 +1,200 @@
PAGE
SBTTL "--- SOFTWARE EQUATES ---"
; -------------------
; MEMORY ORGANIZATION
; -------------------
BUFFER EQU MSTART ; 256-BYTE DISK BUFFER
GSTAKL EQU MSTART+$100 ; G-STACK LSBS
GSTAKH EQU MSTART+$200 ; G-STACK MSBS
MEMMAP EQU MSTART+$300 ; ABSOLUTE MEMORY MAP
PAGMAP EQU MSTART+$400 ; PAGING BUFFER MAP (128 BYTES)
LRUMAP EQU MSTART+$480 ; LRU MAP (128 BYTES)
VLOWS EQU MSTART+$500 ; LSB PLOT TABLE (192 BYTES)
VHIGHS EQU VLOWS+$C0 ; MSB PLOT TABLE (192 BYTES)
LOCALS EQU VLOWS+$180 ; LOCAL VARIABLE STORAGE (32 BYTES)
CARGS EQU LOCALS+$20 ; CALL ARGUMENT STORAGE (32 BYTES)
CTYPES EQU CARGS+$20 ; CALL ARGUMENT LIST (16 BYTES)
GRIP EQU MSTART+$700 ; BEGINNING OF GRIP CODE
GBEGIN EQU GRIP+$1800 ; START OF PRELOAD
; -----------------
; PROGRAM CONSTANTS
; -----------------
FALSE EQU 0
TRUE EQU $FF
LO EQU 0
HI EQU 1
INTRP EQU 'B' ; INTERPRETER VERSION #
; ---------------------
; G-CODE HEADER OFFSETS
; ---------------------
GVERS EQU 0 ; (BYTE) G-MACHINE VERSION ("1")
GMODE EQU 1 ; (BYTE) MODE BYTE
GID EQU 2 ; (WORD) GAME ID
GEND EQU 4 ; (WORD) END OF G-PRELOAD
GSTART EQU 6 ; (WORD) EXECUTION START ADDRESS
GPUR EQU 8 ; (WORD) START OF PURE G-CODE
GGLOB EQU 10 ; (WORD) START OF GLOBAL VARIABLE TABLE
GSER EQU 12 ; (6 BYTES) ASCII SERIAL NUMBER
GLEN EQU 18 ; (WORD) LENGTH OF G-PROGRAM IN BYTES
GCHECK EQU 20 ; (WORD) G-CODE CHECKSUM
IVERS EQU 22 ; (WORD) INTERPRETER VERSION
; ---------------------
; I-FILE HEADER OFFSETS
; ---------------------
ILEN EQU 0 ; (WORD) I-FILE LENGTH IN BYTES
IEND EQU 2 ; (WORD) END OF I-FILE PRELOAD
ICHECK EQU 4 ; (WORD) I-FILE CHECKSUM WORD
IBLKS EQU 6 ; (BYTE) # BLOCKSETS IN FILE
IICONS EQU 7 ; (BYTE) # ICONS IN FILE
; -------------------
; ZERO-PAGE VARIABLES
; -------------------
OPCODE EQU ZSTART ; (BYTE) CURRENT OPCODE
NARGS EQU OPCODE+1 ; (BYTE) CURRENT # ARGUMENTS
ARG1 EQU OPCODE+2 ; (WORD) ARGUMENT 1 REGISTER
ARG2 EQU OPCODE+4 ; (WORD) ARGUMENT 2 REGISTER
ARG3 EQU OPCODE+6 ; (WORD) ARGUMENT 3 REGISTER
ARG4 EQU OPCODE+8 ; (WORD) ARGUMENT 4 REGISTER
ABYTE EQU OPCODE+10 ; (BYTE) X-OP ARGUMENT BYTE
ADEX EQU OPCODE+11 ; (BYTE) X-OP ARGUMENT INDEX
ADEX2 EQU OPCODE+12 ; (BYTE) "CALL" ARG-BYTE INDEX
VALUE EQU OPCODE+13 ; (WORD) VALUE RETURN REGISTER
I EQU VALUE+2 ; (WORD) GENERAL INDEX REGISTER #1
J EQU VALUE+4 ; (WORD) GENERAL INDEX REGISTER #2
K EQU VALUE+6 ; (WORD) " " " #3
GPC EQU VALUE+8 ; (WORD) G-CODE PROGRAM COUNTER
GPCL EQU GPC ; (BYTE) LSB OF GPC
GPCH EQU GPC+1 ; (BYTE) MSB OF GPC
;***
GPC0: EQU GPC+2 ; (BYTE) BIT 0 OF BYTE IS BIT 0 OF GPC
;***
GPCFLG EQU GPC+3 ; (BYTE) GPC VALIDITY FLAG
GPOINT EQU GPC+4 ; (WORD) ABSOLUTE G-MEMORY POINTER
VPC EQU GPC+6 ; (WORD) VIRTUAL MEMORY POINTER
VPCL EQU VPC ; (BYTE) LSB OF VPC
VPCH EQU VPC+1 ; (BYTE) MSB OF VPC
;***
VPC0 EQU VPC+2 ; (BYTE) LEAST SIG BIT OF VPC
;***
VPCFLG EQU VPC+3 ; (BYTE) VPC VALIDITY FLAG
VPOINT EQU VPC+4 ; (WORD) ABSOLUTE V-MEMORY POINTER
VPCSAV EQU VPC+6 ; (WORD) [VPC] SAVE REGISTER
GSP EQU VPC+8 ; (BYTE) G-STACK POINTER
OLDGSP EQU GSP+1 ; (BYTE) OLD G-STACK POINTER
GCODE EQU GSP+2 ; (BYTE) ABS 1ST PAGE OF G-PRELOAD
ICODE EQU GCODE+1 ; (WORD) ABS START ADDR OF I-PRELOAD
GPURE EQU GCODE+3 ; (BYTE) 1ST V-PAGE OF "PURE" G-CODE
ISTART EQU GPURE+1 ; (BYTE) 1ST V-PAGE OF I-FILE
IPURE EQU GPURE+2 ; (BYTE) 1ST V-PAGE OF "PURE" I-FILE
PAGE0 EQU GPURE+3 ; (BYTE) ABS 1ST PAGE OF PAGING SPACE
PMAX EQU PAGE0+1 ; (BYTE) MAXIMUM # SWAPPING PAGES
STAMP EQU PAGE0+2 ; (BYTE) LRU TIMESTAMP
LRU EQU PAGE0+3 ; (BYTE) EARLIEST TIMESTAMP
SWAP EQU PAGE0+4 ; (BYTE) LRU SWAPPING PAGE
TARGET EQU PAGE0+5 ; (BYTE) TARGET BUFFER ADDRESS
GLOBAL EQU PAGE0+6 ; (WORD) ABSOLUTE GLOBAL TABLE ADDR
BTAB EQU GLOBAL+2 ; (WORD) ABSOLUTE BLOCKSET TABLE ADDR
ITAB EQU GLOBAL+4 ; (WORD) ABSOLUTE ICON TABLE ADDR
NBLOKS EQU GLOBAL+6 ; (BYTE) # BLOCKSETS IN I-FILE
NICONS EQU GLOBAL+7 ; (BYTE) # ICONS IN I-FILE
QUOT EQU GLOBAL+8 ; (WORD) QUOTIENT REGISTER
REMAIN EQU QUOT+2 ; (WORD) REMAINDER REGISTER
MTEMP EQU QUOT+4 ; (WORD) TEMP MATH REGISTER
QSIGN EQU QUOT+6 ; (BYTE) SIGN OF QUOTIENT
RSIGN EQU QUOT+7 ; (BYTE) SIGN OF REMAINDER
MUSHFT EQU QUOT+8 ; (BYTE) MULTIPLY TEMP FOR BLOCKS
MUL EQU QUOT+9 ; (BYTE) DITTO
MUH EQU QUOT+10 ; (BYTE) DITTO
IADR1 EQU QUOT+11 ; (WORD) ABS ADDR OF ICON #1
;***
IADR10 EQU IADR1+2 ; (BYTE) SAME IDEA AS VPC0
;***
IADR2 EQU IADR1+3 ; (WORD) ABS ADDR OF ICON #2
;***
IADR20 EQU IADR1+5 ; (BYTE) SAME IDEA AS VPC0
;***
IX1 EQU IADR1+6 ; (BYTE) X-SIZE OF ICON #1
IX2 EQU IADR1+7 ; (BYTE) X-SIZE OF ICON #2
IY1 EQU IADR1+8 ; (BYTE) Y-SIZE OF ICON #1
IY2 EQU IADR1+9 ; (BYTE) Y-SIZE OF ICON #2
XDEX1 EQU IADR1+10 ; (BYTE) X-INDEX #1
XDEX2 EQU IADR1+11 ; (BYTE) X-INDEX #2
YDEX1 EQU IADR1+12 ; (BYTE) Y-INDEX #1
YDEX2 EQU IADR1+13 ; (BYTE) Y-INDEX #2
ITERS EQU IADR1+14 ; (BYTE) # ICON ITERATIONS
ITICN EQU IADR1+15 ; (BYTE) COUNTER FOR ITERATE ROUTINE
ITPNT EQU IADR1+16 ; (BYTE) COUTNER FOR ITERATE ROUTINE
XPOS EQU IADR1+17 ; (WORD) ICON X-POSITION
YPOS EQU IADR1+19 ; (WORD) ICON Y-POSITION
TOPCUT EQU IADR1+21 ; (BYTE) TEMP FOR AMOUNT TO CUT OFF TOP IN SET
; UP ROUTINE OF SHOWI
SIDCUT EQU IADR1+22 ; (BYTE) SAME AS TOPCUT FOR SIDE
IXSKIP EQU IADR1+23 ; (BYTE) AMOUNT TO ADD TO IADR1 TO GET NEXT
; BLOCK AT NEXT ROW
MDXCUT EQU IADR1+24 ; (BYTE) IF YOU DON'T UNDERSTAND, OH WELL.
;MDYCUT EQU IADR1+25 ; (BYTE) NOT SHURE THIS IS USED IN FINAL
WINDX1 EQU IADR1+26 ; (BYTE) LEFT CLIP VALUE
WINDY1 EQU WINDX1+1 ; (BYTE) RIGHT CLIP VALUE
WINDX2 EQU WINDX1+2 ; (BYTE) TOP CLIP VALUE
WINDY2 EQU WINDX1+3 ; (BYTE) BOTTOM CLIP VALUE
WINDH EQU WINDX1+4 ; (BYTE) HEIGHT OF WINDOW (WINDY2-WINDY1)
WINDW EQU WINDX1+5 ; (BYTE) WIDTH OF WINDOW (WINDX2-WINDX1)
BSET EQU WINDX1+6 ; (BYTE) CURRENT BLOCKSET ID
BSADR EQU BSET+1 ; (WORD) ABS ADDR OF CURRENT BLOCKSET
BSIZE EQU BSET+3 ; (BYTE) # BLOCKS IN CURRENT BLOCKSET
BLOCK EQU BSET+4 ; (8 BYTES) IMAGE BLOCK BUFFER
MASK EQU BSET+12 ; (8 BYTES) IMAGE MASK BUFFER
MSKFLG EQU BSET+20 ; (BYTE) FLAG FOR MASKING 00=DISABLED
TOX EQU BSET+21 ; (BYTE) X-SAVE FOR "DUMP"
XPSAV EQU BSET+22 ; (WORD) X-POSITION SAVE
XCURS EQU BSET+24 ; (BYTE) GAME CURSOR X-POS
YCURS EQU BSET+25 ; (BYTE) GAME CURSOR Y-POS
NEGATE EQU BSET+26 ; (BYTE) BLOCK NEGATE FLAG
BLKLEN EQU BSET+27 ; (BYTE) # BYTES PER BLOCK
DBLOCK EQU BSET+28 ; (BYTE) G-CODE BLOCK TO ACCESS
DBTOP EQU DBLOCK+1 ; (BYTE) MSB HOLDER FOR "GETDSK"
DBUFF EQU DBLOCK+2 ; (WORD) DISK BUFFER PAGE POINTER
SECTOR EQU DBLOCK+4 ; (WORD) SECTOR ADDRESS
;***
DCNT EQU DBLOCK+6 ; (BYTE) COUNTER FOR GROS
;***
LINE EQU DBLOCK+7 ; (WORD) TEXT LINE ADDRESS
LEN EQU LINE+2 ; (BYTE) TEXT LINE LENGTH
CURSOR EQU LINE+3 ; (BYTE) TEXT CURSOR POSITION (0-39)
CHKSUM EQU LINE+4 ; (WORD) HOLDS IMAGE CHECKSUM FOR VERIFY
END

136
atari/eq.src Normal file
View File

@@ -0,0 +1,136 @@
PAGE
SBTTL "--- MEMORY ORGANIZATION ---"
TRUE EQU $FF
FALSE EQU 0
LO EQU 0
HI EQU 1
; SEE "HARDEQ.ASM" FOR ATARI MEMORY MAP
; ---------------------
; Z-CODE HEADER OFFSETS
; ---------------------
ZVERS EQU 0 ; VERSION BYTE
ZMODE EQU 1 ; MODE SELECT BYTE
ZID EQU 2 ; GAME ID WORD
ZENDLD EQU 4 ; START OF NON-PRELOADED Z-CODE
ZGO EQU 6 ; EXECUTION ADDRESS
ZVOCAB EQU 8 ; START OF VOCABULARY TABLE
ZOBJEC EQU 10 ; START OF OBJECT TABLE
ZGLOBA EQU 12 ; START OF GLOBAL VARIABLE TABLE
ZPURBT EQU 14 ; START OF "PURE" Z-CODE
ZSCRIP EQU 16 ; FLAG WORD
ZSERIA EQU 18 ; 3-WORD ASCII SERIAL NUMBER
ZFWORD EQU 24 ; START OF FWORDS TABLE
ZLENTH EQU 26 ; LENGTH OF Z-PROGRAM IN WORDS
ZCHKSM EQU 28 ; Z-CODE CHECKSUM WORD
PAGE
SBTTL "--- ZIP Z-PAGE VARIABLES ---"
OPCODE EQU ZEROPG ; (BYTE) CURRENT OPCODE
NARGS EQU OPCODE+1 ; (BYTE) # ARGUMENTS
ARG1 EQU OPCODE+2 ; (WORD) ARGUMENT #1
ARG2 EQU OPCODE+4 ; (WORD) ARGUMENT #2
ARG3 EQU OPCODE+6 ; (WORD) ARGUMENT #3
ARG4 EQU OPCODE+8 ; (WORD) ARGUMENT #4
ABYTE EQU OPCODE+10 ; (BYTE) X-OP ARGUMENT BYTE
ADEX EQU OPCODE+11 ; (BYTE) X-OP ARGUMENT INDEX
VALUE EQU OPCODE+12 ; (WORD) VALUE RETURN REGISTER
I EQU VALUE+2 ; (WORD) GEN-PURPOSE REGISTER #1
J EQU VALUE+4 ; (WORD) GEN-PURPOSE REGISTER #2
K EQU VALUE+6 ; (WORD) GEN-PURPOSE REGISTER #3
ZSP EQU VALUE+8 ; (BYTE) Z-STACK POINTER
OLDZSP EQU ZSP+1 ; (BYTE) OLD Z-STACK POINTER
ZPC EQU ZSP+2 ; (3 BYTES) ZIP PROGRAM COUNTER
ZPCL EQU ZPC ; (BYTE) LOW 8 BITS OF [ZPC]
ZPCM EQU ZPC+1 ; (BYTE) MIDDLE 8 BITS OF [ZPC]
ZPCH EQU ZPC+2 ; (BYTE) HIGH BIT OF [ZPC]
ZPCFLG EQU ZPC+3 ; (BYTE) FLAG: "TRUE" IF [ZPCPNT] VALID
ZPCPNT EQU ZPC+4 ; (WORD) ABS POINTER TO CURRENT Z-PAGE
MPC EQU ZPC+6 ; (3 BYTES) MEMORY PROGRAM COUNTER
MPCL EQU MPC ; (BYTE) LOW 8 BITS OF [MPC]
MPCM EQU MPC+1 ; (BYTE) MIDDLE 8 BITS OF [MPC]
MPCH EQU MPC+2 ; (BYTE) HIGH BIT OF [MPC]
MPCFLG EQU MPC+3 ; (BYTE) FLAG: "TRUE" IF [MPCPNT] VALID
MPCPNT EQU MPC+4 ; (WORD) ABS POINTER TO CURRENT M-PAGE
LRU EQU MPC+6 ; (BYTE) EARLIEST TIMESTAMP
ZCODE EQU LRU+1 ; (BYTE) 1ST ABSOLUTE PAGE OF PRELOAD
ZPURE EQU LRU+2 ; (BYTE) 1ST VIRTUAL PAGE OF "PURE" Z-CODE
PAGE0 EQU LRU+3 ; (BYTE) 1ST PAGE OF ACTUAL SWAPPING SPACE
PMAX EQU LRU+4 ; (BYTE) MAXIMUM # OF SWAPPING PAGES
ZPAGE EQU LRU+5 ; (BYTE) CURRENT SWAPPING PAGE
TARGET EQU LRU+6 ; (WORD) TARGET PAGE FOR SWAPPING
STAMP EQU LRU+8 ; (BYTE) CURRENT TIMESTAMP
SWAP EQU LRU+9 ; (BYTE) EARLIEST BUFFER
GLOBAL EQU LRU+10 ; (WORD) GLOBAL VARIABLE POINTER
VOCAB EQU GLOBAL+2 ; (WORD) VOCAB TABLE POINTER
FWORDS EQU GLOBAL+4 ; (WORD) F-WORDS TABLE POINTER
OBJTAB EQU GLOBAL+6 ; (WORD) OBJECT TABLE POINTER
; Z-STRING MANIPULATION VARIABLES
IN EQU GLOBAL+8 ; (6 BYTES) INPUT BUFFER
OUT EQU IN+6 ; (6 BYTES) OUTPUT BUFFER
SOURCE EQU OUT+6 ; (BYTE) SOURCE BUFFER POINTER
RESULT EQU SOURCE+1 ; (BYTE) RESULT TABLE POINTER
LINLEN EQU SOURCE+2 ; (BYTE) LENGTH OF CURRENT LINE
WRDLEN EQU SOURCE+3 ; (BYTE) LENGTH OF CURRENT WORD
ENTRY EQU SOURCE+4 ; (WORD) ADDR OF CURRENT RESULT ENTRY
NENTS EQU SOURCE+6 ; (WORD) # ENTRIES IN VOCAB TABLE
ESIZE EQU SOURCE+8 ; (BYTE) SIZE OF VOCAB TABLE ENTRIES
PSET EQU SOURCE+9 ; (BYTE) PERMANENT CHARSET
TSET EQU SOURCE+10 ; (BYTE) TEMPORARY CHARSET
ZCHAR EQU SOURCE+11 ; (BYTE) CURRENT Z-CHAR
OFFSET EQU SOURCE+12 ; (BYTE) F-WORD TABLE OFFSET
ZFLAG EQU SOURCE+13 ; (BYTE) Z-WORD ACCESS FLAG
ZWORD EQU SOURCE+14 ; (WORD) CURRENT Z-WORD
CONCNT EQU SOURCE+16 ; (BYTE) Z-STRING SOURCE COUNTER
CONIN EQU SOURCE+17 ; (BYTE) CONVERSION SOURCE INDEX
CONOUT EQU SOURCE+18 ; (BYTE) CONVERSION DEST INDEX
QUOT EQU SOURCE+19 ; (WORD) QUOTIENT FOR DIVISION
REMAIN EQU QUOT+2 ; (WORD) REMAINDER FOR DIVISION
MTEMP EQU QUOT+4 ; (WORD) MATH TEMPORARY REGISTER
QSIGN EQU QUOT+6 ; (BYTE) SIGN OF QUOTIENT
RSIGN EQU QUOT+7 ; (BYTE) SIGN OF REMAINDER
DIGITS EQU QUOT+8 ; (BYTE) DIGIT COUNT FOR "PRINTN"
TIMEFL EQU QUOT+9 ; (BYTE) "TRUE" IF TIME MODE
LENGTH EQU TIMEFL+1 ; (BYTE) LENGTH OF LINE IN [LINBUF]
OLDLEN EQU TIMEFL+2 ; (BYTE) OLD LINE LENGTH
SCRIPT EQU TIMEFL+3 ; (BYTE) SCRIPT ENABLE FLAG
LINCNT EQU TIMEFL+4 ; (BYTE) LINE COUNTER
LMAX EQU TIMEFL+5 ; (BYTE) MAX # LINES/SCREEN
IOCHAR EQU TIMEFL+6 ; (BYTE) CHARACTER BUFFER
SLINE EQU IOCHAR+1 ; (BYTE) BORDERLINE FOR SPLIT
SPSTAT EQU IOCHAR+2 ; (BYTE) SPLIT SCREEN STATUS FLAG
LFROM EQU IOCHAR+3 ; (WORD) "FROM" LINE ADDRESS
LTO EQU IOCHAR+5 ; (WORD) "TO" LINE ADDRESS
PSTAT EQU IOCHAR+7 ; (BYTE) PRINTER STATUS FLAG
PRLEN EQU IOCHAR+8 ; (BYTE) SCRIPT LINE LENGTH
DBLOCK EQU IOCHAR+9 ; (WORD) Z-BLOCK TO READ
DBUFF EQU DBLOCK+2 ; (WORD) RAM PAGE TO ACCESS (LSB = 0)
SECTOR EQU DBLOCK+4 ; (WORD) TARGET SECTOR
GPOSIT EQU DBLOCK+6 ; (BYTE) DEFAULT SAVE POSITION
GDRIVE EQU DBLOCK+7 ; (BYTE) DEFAULT SAVE DRIVE
TPOSIT EQU DBLOCK+8 ; (BYTE) TEMP SAVE POSITION
TDRIVE EQU DBLOCK+9 ; (BYTE) TEMP SAVE DRIVE
DRIVE EQU DBLOCK+10 ; (BYTE) CURRENT DRIVE
BLINK EQU DBLOCK+11 ; (WORD) CURSOR BLINK TIMER
CSHAPE EQU BLINK+2 ; (BYTE) CURRENT CURSOR SHAPE
END

95
atari/grip.dip Normal file
View File

@@ -0,0 +1,95 @@
TITLE "GRIP/6502 INFOCOM COMPANY PRIVATE --- INITIALIZATION"
PGLEN 54
; ----------------------------
; GRIP/6502 1.0
; G-CODE INTERPRETER PROGRAM
; FOR ATARI 400/800/1200/XL
; ----------------------------
; INFOCOM, INC.
; 55 WHEELER STREET
; CAMBRIDGE, MA 02138
; COMPANY PRIVATE -- NOT FOR DISTRIBUTION
; -------------------------
; MEMORY ALLOCATION EQUATES
; -------------------------
; THESE MUST BE DEFINED FOR EACH MACHINE
;ZSTART EQU $80 ; FIRST FREE ZERO-PAGE LOCATION
;***
;ZSTART EQU $7E ; FIRST FREE ZERO-PAGE LOCATION
;***
;***
ZSTART EQU $6B ; FIRST FREE ZERO-PAGE LOCATION
;***
ZEND EQU $FF ; LAST FREE ZERO-PAGE LOCATION
MSTART EQU $0400 ; FIRST FREE RAM LOCATION
DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER
; -----------
; ERROR CODES
; -----------
; 00 -- GAME PRELOAD TOO BIG
; 01 -- IMAGE PRELOAD TOO BIG
; 02 -- UNDEFINED X-OP
; 03 -- UNDEFINED 0-OP
; 04 -- UNDEFINED 1-OP
; 05 -- UNDEFINED 2-OP
; 06 -- G-STACK UNDERFLOW
; 07 -- G-STACK OVERFLOW
; 08 -- DIVISION BY ZERO
; 09 -- PURITY VIOLATION (PUT/PUTB/ITER)
; 0A -- DISK ADDRESS RANGE
; 0B -- DISK ACCESS
; 0C -- NO CALL ADDRESS
; 0D -- UNDEFINED SOUND
; 0E -- PURITY VIOLATION (SETI/SWAPI)
; ----------------
; BATCH PROCESSING
; ----------------
INCLUD EQ.ASM
INCLUD HARDEQ.ASM ; M
INCLUD COLD.ASM ; M
INCLUD WARM.ASM
TITLE "GRIP/6502 INFOCOM COMPANY PRIVATE --- MAIN LOOP"
INCLUD MAIN.ASM
INCLUD SUBS.ASM
INCLUD DISPATCH.ASM
TITLE "GRIP/6502 INFOCOM COMPANY PRIVATE --- OPCODE EXECUTORS"
INCLUD OPS0.ASM
INCLUD OPS1.ASM
INCLUD OPS2.ASM
INCLUD OPSX.ASM
INCLUD IO.ASM
INCLUD ITERS.ASM
INCLUD IOSUBS.ASM
TITLE "GRIP/6502 INFOCOM COMPANY PRIVATE -- MEMORY MANAGEMENT"
INCLUD PAGING.ASM
TITLE "GRIP/6502 INFOCOM COMPANY PRIVATE -- MACHINE DEPENDENT"
INCLUD MACHINE.ASM ; M
INCLUD SOUND.ASM ; M
INCLUD SAVE.ASM ; M
INCLUD GROS.ASM ; M
IF DEBUG
INCLUD BUGGER.ASM
ENDIF
TITLE "GRIP/6502 INFOCOM COMPANY PRIVATE --- SYMBOL TABLE"
END

148
atari/gros.dip Normal file
View File

@@ -0,0 +1,148 @@
PAGE
SBTTL "--- GRIP OPERATING SYSTEM: ATARI ---"
GAME EQU 3*18+1 ; 1ST G-CODE BLOCK (55; TRACK 3, SECTOR 1)
IMAGE EQU 14*18+1 ; 1ST I-FILE BLOCK (253; TRACK 14, SECTOR 1)
BUFTOP EQU BUFFER+$80 ; TOP HALF OF [BUFFER]
;--------------------------------------------------
; FETCH VIRTUAL PAGE [DBLOCK] AND PUT AT RAM PAGES
; [DBUFF],[DBUFF]+1.
; ON EXIT POINT [DBLOCK] AT NEXT V-PAGE AND POINT
; [DBUFF] TO NEXT RAM PAGE
;--------------------------------------------------
; ----------------
; GET A DISK BLOCK
; ----------------
GETDSK: LDX #0
STX DBTOP ; CLEAR MSB OF BLOCK INDEX
INX ; = 1
STX DUNIT ; ALWAYS USE DRIVE #1
STX DCNT ; COUNTER FOR LOOP TO GET (2) 256 BYTE PAGES
LDA #$52 ; SIO "READ" COMMAND
STA DCOMND
; CALC WHICH DISK SECTORS TO GET
LDA DBLOCK ; GET THE VIRTUAL PAGE INDEX
CMP ISTART ; IT IS BELOW THE IMAGE FILE?
BCC GETGAM ; IF SO, IT'S IN THE GAME FILE
; GET BLOCK [A] FROM THE IMAGE FILE
SBC ISTART ; ZERO-ALIGN THE BLOCK INDEX
ASL A ; * 2 FOR ATARI 128-BYTE SECTORS
ROL DBTOP ; BUILD MSB
; ENTRY POINT FOR VERIFY
GETIMG: ASL A ; * 2 AGAIN FOR 512 BYTE PAGES
ROL DBTOP
CLC
ADC #LOW IMAGE ; ADD THE PHYSICAL I-FILE OFFSET
TAX ; SAVE LSB HERE
LDA DBTOP ; DO MSB
ADC #HIGH IMAGE
JMP DODSK
; GET BLOCK [A] FROM THE GAME FILE
GETGAM: ASL A ; * 2 FOR 128-BYTE SECTORS
ROL DBTOP
; ENTRY POINT FOR VERIFY
GETGME: ASL A ; * 2 AGAIN FOR 512 BYTE PAGES
CLC
ADC #LOW GAME ; ADD THE PHYSICAL G-FILE OFFSET
TAX ; SAVE LSB HERE
LDA DBTOP ; TAKE CARE OF MSB
ADC #HIGH GAME
; VALIDATE SECTOR ADDRESS IN [X/A] (LSB/MSB)
; MUST BE NO HIGHER THAN 717 ($02CD)
DODSK: CMP #$02 ; MSB OUT OF RANGE?
BCC ROK ; OK IF MSB < 2
BEQ T717 ; CHECK LSB IF MSB = 2
; *** ERROR #10: DISK ADDRESS RANGE ***
RANGE: LDA #10
JMP GERROR
T717: CPX #$CE ; MSB WAS 2; IS LSB > $CD?
BCS RANGE ; RANGE ERROR IF SO
ROK: STX SECTOR+LO
STA SECTOR+HI
DSKLP1: LDA SECTOR+LO
STA DAUX1 ; LSB OF SECTOR ADDRESS
LDA SECTOR+HI
STA DAUX2 ; MSB OF SECTOR ADDRESS
LDA #LOW BUFFER
STA DBUFLO
LDA #HIGH BUFFER
STA DBUFHI
; FETCH DISK BLOCK INTO [BUFFER]
JSR DSKINV ; GET 1ST HALF OF BLOCK
LDA DSTATS ; IF STATUS IS NEGATIVE,
BMI DERR ; SOMETHING WENT WRONG
LDA #LOW BUFTOP ; POINT TO
STA DBUFLO ; TOP HALF-PAGE
LDA #HIGH BUFTOP ; OF [BUFFER]
STA DBUFHI
INC SECTOR+LO ; ALSO POINT
BNE DODSK1 ; TO THE
INC SECTOR+HI ; NEXT SECTOR
DODSK1: LDA SECTOR+LO
STA DAUX1
LDA SECTOR+HI
STA DAUX2
JSR DSKINV ; GET 2ND HALF OF BLOCK
LDA DSTATS ; ERROR IF
BMI DERR ; [DSTATS] RETURNED NEGATIVE
; MOVE [BUFFER] TO PAGE [DBUFF]
LDY #0
STY DBUFF+LO ; MAKE SURE LSB IS ZEROED!
MOVEB: LDA BUFFER,Y
STA (DBUFF),Y
INY
BNE MOVEB
INC DBUFF+HI ; POINT TO NEXT RAM PAGE
DEC DCNT
BMI DSKP1
INC SECTOR+LO
BNE DSKP0
INC SECTOR+HI
DSKP0: JMP DSKLP1
DSKP1: INC DBLOCK ; POINT TO NEXT VIRTUAL PAGE
RTS
; *** ERROR #11: DISK ACCESS ***
DERR: LDA #11
JMP GERROR
END

94
atari/hardeq.dip Normal file
View File

@@ -0,0 +1,94 @@
PAGE
SBTTL "--- HARDWARE EQUATES: ATARI ---"
SCREEN EQU $A100 ; START OF SCREEN RAM
; ----------------------
; ATARI HARDWARE EQUATES
; ----------------------
; ZER0-PAGE
BOOT EQU $09 ; BOOT FLAG
DOSVEC EQU $0A ; DOS START VECTOR
DOSINI EQU $0C ; DOS INIT VECTOR
POKMSK EQU $10 ; FOR BREAK KEY DISABLE
BRKKEY EQU $11 ; BREAK KEY FLAG
RTCLOK EQU $14 ; JIFFY CLOCK
SOUNDR EQU $41 ; NOISY I/O FLAG
ATRACT EQU $4D ; ATTRACT MODE FLAG
ROWCRS EQU $54 ; OS CURSOR ROW
COLCRS EQU $55 ; OS CURSOR COLUMN
SAVMSC EQU $58 ; OS SCREEN ADDRESS
RAMTOP EQU $6A ; OS TOP OF RAM
FR0 EQU $D4 ; FP REGISTER #0
FR1 EQU $E0 ; FP REGISTER #1
CIX EQU $F2 ; FP INDEX
INBUFF EQU $F3 ; ASCII BUFFER POINTER
; PAGES 2-5
SDMCTL EQU $022F ; DMA CONTROL
SDLSTL EQU $0230 ; DISPLAY LIST ADDRESS
COLDST EQU $0244 ; COLDSTART FLAG
STICK0 EQU $0278 ; JOYSTICK #0
STICK1 EQU $0279 ; JOYSTICK #1
STRIG0 EQU $0284 ; JOYSTICK #0 TRIGGER
STRIG1 EQU $0285 ; JOYSTICK #1 TRIGGER
COLOR1 EQU $02C5 ; GRAPHICS FOREGROUND COLOR
COLOR2 EQU $02C6 ; BACKGROUND COLOR
RAMSIZ EQU $02E4 ; AMOUNT OF RAM IN SYSTEM
CRSINH EQU $02F0 ; OS CURSOR INHIBIT
CH EQU $02FC ; KEYBOARD READ FLAG
DUNIT EQU $0301 ; DRIVE #
DCOMND EQU $0302 ; DISK COMMAND
DSTATS EQU $0303 ; DISK I/O STATUS
DBUFLO EQU $0304 ; DISK BUFFER ADDR (LSB)
DBUFHI EQU $0305 ; DISK BUFFER ADDR (MSB)
DAUX1 EQU $030A ; SECTOR ADDR (LSB)
DAUX2 EQU $030B ; SECTOR ADDR (MSB)
ICCOM EQU $0342 ; IOCB #0 COMMAND
ICBADR EQU $0344 ; IOCB #0 BUFFER ADDR
ICBLEN EQU $0348 ; IOCB #0 LENGTH
ICAUX1 EQU $034A ; IOCB #0 AUX BYTE #1
ICAUX2 EQU $034B ; IOCB #0 AUX BYTE #2
TEXT EQU $03A0 ; TEXT BUFFER
LBUFF EQU $0580 ; ASCII OUTPUT BUFFER
; GTIA, POKEY, ANTIC
CONSOL EQU $D01F ; CONSOLE KEY REGISTER
AUDF1 EQU $D200 ; AUDIO CH1 FREQ
AUDC1 EQU $D201 ; AUDIO CH1 CTRL
AUDF2 EQU $D202 ; AUDIO CH2 FREQ
AUDC2 EQU $D203 ; AUDIO CH2 CTRL
AUDF3 EQU $D204 ; AUDIO CH3 FREQ
AUDC3 EQU $D205 ; AUDIO CH3 CTRL
AUDF4 EQU $D206 ; AUDIO CH4 FREQ
AUDC4 EQU $D207 ; AUDIO CH4 CTRL
AUDCTL EQU $D208 ; AUDIO CONTROL
RANDOM EQU $D20A ; RANDOM BYTE
IRQEN EQU $D20E ; IRQ ENABLE
SKCTL EQU $D20F ; SERIAL PORT CONTROL
PORTB EQU $D301 ; PORT B (XL ROM SWITCH)
DMACTL EQU $D400 ; DMA CONTROL
; OS ROM
FASC EQU $D8E6 ; FP TO ASCII
IFP EQU $D9AA ; INTEGER TO FP
FPI EQU $D9D2 ; FP TO INTEGER
ZFR0 EQU $DA44 ; CLEAR FR0
ZFR1 EQU $DA46 ; CLEAR FR1
FSUB EQU $DA60 ; FP SUBTRACT
FADD EQU $DA66 ; FP ADD
FMUL EQU $DADB ; FP MULTIPLY
FDIV EQU $DB28 ; FP DIVIDE
FMOVE EQU $DDB6 ; MOVE FR0 TO FR1
DSKINV EQU $E453 ; SIO DISK ACCESS
CIOV EQU $E456 ; CIO VECTOR
SIOINV EQU $E465 ; SIO INIT (FOR SOUND)
COLDSV EQU $E477 ; COLDSTART VECTOR
END

105
atari/hardeq.src Normal file
View File

@@ -0,0 +1,105 @@
PAGE
SBTTL "--- HARDWARE EQUATES: ATARI ---"
; ----------------
; ATARI MEMORY MAP
; ----------------
IOBUFF EQU $0400 ; DISK I/O BUFFER
BUFTOP EQU $0480 ; TOP HALF OF I/O BUFFER
ZSTAKL EQU $0500 ; Z-STACK LSBS
ZSTAKH EQU $0600 ; Z-STACK MSBS
PTABL EQU $0700 ; PAGING TABLE LSBS
PTABH EQU $0800 ; PAGING TABLE MSBS
LRUMAP EQU $0900 ; TIMESTAMP MAP
LOCALS EQU $0A00 ; LOCAL VARIABLE STORAGE (30 BYTES)
BUFSAV EQU $0A20 ; AUXILIARY INPUT BUFFER (80 BYTES)
LBUFF EQU $0A80 ; MAIN INPUT BUFFER (80 BYTES)
PLMRAM EQU $0800 ; START OF PLAYER/MISSILE RAM
MISSL EQU $0B00 ; START OF MISSILE RAM (CURSOR)
ZIP EQU $0C00 ; START OF ZIP CODE
ZBEGIN EQU $2600 ; START OF Z-CODE (ASSUME 6.5K ZIP)
OLDLST EQU $BC20 ; CIO DEFAULT DL ADDR
SCREEN EQU $BC40 ; START OF SCREEN RAM
; ---------
; CONSTANTS
; ---------
XSIZE EQU 39 ; WIDTH OF SCREEN IN CHARACTERS (-1)
YSIZE EQU 23 ; HEIGHT OF SCREEN IN LINES (-1)
EOL EQU $9B ; EOL CHAR
SPACE EQU $20 ; SPACE CHAR
BACKSP EQU 126 ; BACKSPACE
; ---------
; ZER0-PAGE
; ---------
BOOT EQU $09 ; BOOT FLAG
DOSVEC EQU $0A ; DOS START VECTOR
POKMSK EQU $10 ; FOR BREAK KEY DISABLE
RTCLOK EQU $14 ; JIFFY CLOCK
LMARGN EQU $52 ; LEFT MARGIN
ROWCRS EQU $54 ; OS CURSOR ROW
COLCRS EQU $55 ; OS CURSOR COLUMN
; ---------
; PAGES 2-3
; ---------
SDMCTL EQU $022F ; DMA CONTROL
SDLSTL EQU $0230 ; DISPLAY LIST ADDRESS
COLDST EQU $0244 ; COLDSTART FLAG
GPRIOR EQU $026F ; GRAPHICS PRIORITY
LOGMAP EQU $02B2 ; LOGICAL LINE MAP (3 BYTES)
INVFLG EQU $02B6 ; INVERSE TEXT FLAG
COLOR1 EQU $02C5 ; TEXT COLOR
COLOR4 EQU $02C8 ; BORDER COLOR
CRSINH EQU $02F0 ; OS CURSOR INHIBIT
CH EQU $02FC ; KEYBOARD READ FLAG
DUNIT EQU $0301 ; DRIVE #
DCOMND EQU $0302 ; DISK COMMAND
DSTATS EQU $0303 ; DISK I/O STATUS
DBUFLO EQU $0304 ; DISK BUFFER ADDR (LSB)
DBUFHI EQU $0305 ; DISK BUFFER ADDR (MSB)
DAUX1 EQU $030A ; SECTOR ADDR (LSB)
DAUX2 EQU $030B ; SECTOR ADDR (MSB)
ICCOM EQU $0342 ; IOCB #0 COMMAND
ICBADR EQU $0344 ; IOCB #0 BUFFER ADDR
ICBLEN EQU $0348 ; IOCB #0 LENGTH
ICAUX1 EQU $034A ; IOCB #0 AUX BYTE #1
ICAUX2 EQU $034B ; IOCB #0 AUX BYTE #2
; ------------------
; GTIA, POKEY, ANTIC
; ------------------
HPOSP0 EQU $D000 ; PLAYER #0 H-POS
HPOSM0 EQU $D004 ; MISSILE #0 H-POS
SIZEM EQU $D00C ; MISSILE SIZES
GRACTL EQU $D01D ; P/M GRAPHICS CONTROL
CONSOL EQU $D01F ; CONSOLE KEY REGISTER
AUDF1 EQU $D200 ; AUDIO CH1 FREQ
AUDC1 EQU $D201 ; AUDIO CH1 CTRL
AUDCTL EQU $D208 ; AUDIO CONTROL
MRAND EQU $D20A ; RANDOM BYTE
IRQEN EQU $D20E ; IRQ ENABLE
SKCTL EQU $D20F ; SERIAL PORT CONTROL
PORTB EQU $D301 ; PORT B (XL ROM SWITCH)
DMACTL EQU $D400 ; DMA CONTROL
PMBASE EQU $D407 ; PMG RAM BASE ADDR
; ------
; OS ROM
; ------
DSKINV EQU $E453 ; SIO DISK ACCESS
CIOV EQU $E456 ; CIO VECTOR
END

604
atari/io.dip Normal file
View File

@@ -0,0 +1,604 @@
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

502
atari/iosubs.dip Normal file
View File

@@ -0,0 +1,502 @@
PAGE
SBTTL "--- I/O SUPPORT ROUTINES ---"
;-----------------------------------------
; INCRIMENT [VPC]+HI,[VPC]+LO,[VPC0]
;-----------------------------------------
INCVPC: LDA VPC0 ; EFFECTIVLY ADD 1
EOR #$01 ; WITH EOR
STA VPC0
BNE VPEX1
STA VPCFLG ; INVALIDATE FLAG
INC VPC+LO
BNE VPEX1
INC VPC+HI
VPEX1: RTS
;----------------------------
; ADD A,X TO [VPC]+HI,+LO,0
;----------------------------
ADDVPC: STX J+LO ; SAVE <X>
LSR A ; SHIFT SO AS TO ALIGN WITH 8,8,1 BIT PATTERN
; IN [VPC]
STA J+HI
ROR J+LO ; SHIFT LOW PART
BCC AVISK
JSR INCVPC ; IF CARRY SET ADD 1 TO [VPC]
CLC
AVISK: LDA VPC+LO
ADC J+LO
STA VPC+LO
LDA VPC+HI
ADC J+HI
STA VPC+HI
LDA #00 ; INVALIDATE FLAG
STA VPCFLG
RTS
;-----------------------------------------
; INCRIMENT [GPC]+HI,[GPC]+LO,[GPC0]
;-----------------------------------------
INCGPC: LDA GPC0 ; EFFECTIVLY ADD 1
EOR #$01 ; WITH EOR
STA GPC0
BNE GPEX1
STA GPCFLG ; INVALIDATE FLAG
INC GPC+LO
BNE GPEX1
INC GPC+HI
GPEX1: RTS
;----------------------------
; ADD A,X TO [GPC]+HI,+LO,0
;----------------------------
ADDGPC: STX J+LO ; SAVE <X>
LSR A ; SHIFT SO AS TO ALIGN WITH 8,8,1 BIT PATTERN
; IN [GPC]
STA J+HI
ROR J+LO ; SHIFT LOW PART
BCC AGISK
JSR INCGPC ; IF CARRY SET ADD 1 TO [GPC]
CLC
AGISK: LDA GPC+LO
ADC J+LO
STA GPC+LO
LDA GPC+HI
ADC J+HI
STA GPC+HI
LDA #00 ; INVALIDATE FLAG
STA GPCFLG
RTS
;-----------------------------------------
; INCRIMENT [IADR2]+HI,[IADR2]+LO,[IADR20]
;-----------------------------------------
INCIA2: LDA IADR20 ; EFFECTIVLY ADD 1
EOR #$01 ; WITH EOR
STA IADR20
BNE INEX2
INC IADR2+LO
BNE INEX2
INC IADR2+HI
INEX2: RTS
;----------------------------
; ADD A,X TO [IADR2]+HI,+LO,0
;----------------------------
ADDIA2: STX J+LO ; SAVE <X>
LSR A ; SHIFT SO AS TO ALIGN WITH 8,8,1 BIT PATTERN
; IN [IADR2]
STA J+HI
ROR J+LO ; SHIFT LOW PART
BCC ADIS2
JSR INCIA2 ; IF CARRY SET ADD 1 TO [IADR1]
CLC
ADIS2: LDA IADR2+LO
ADC J+LO
STA IADR2+LO
LDA IADR2+HI
ADC J+HI
STA IADR2+HI
RTS
;-----------------------------------------
; INCRIMENT [IADR1]+HI,[IADR1]+LO,[IADR10]
;-----------------------------------------
INCIA1: LDA IADR10 ; EFFECTIVLY ADD 1
EOR #$01 ; WITH EOR
STA IADR10
BNE INEX1
INC IADR1+LO
BNE INEX1
INC IADR1+HI
INEX1: RTS
;----------------------------
; ADD A,X TO [IADR1]+HI,+LO,0
;----------------------------
ADDIA1: STX J+LO ; SAVE <X>
LSR A ; SHIFT SO AS TO ALIGN WITH 8,8,1 BIT PATTERN
; IN [IADR1]
STA J+HI
ROR J+LO ; SHIFT LOW PART
BCC ADISK
JSR INCIA1 ; IF CARRY SET ADD 1 TO [IADR1]
CLC
ADISK: LDA IADR1+LO
ADC J+LO
STA IADR1+LO
LDA IADR1+HI
ADC J+HI
STA IADR1+HI
RTS
; ----------------
; GET BLOCKSET [A]
; ----------------
; ENTRY: BLOCKSET ID # (1-255) IN [A]
; EXIT: VIRTUAL BASE ADDR OF BLOCKSET DATA IN [BSADR]
; # BLOCKS IN [BSIZE]
; BLOCKSET DATA PAGED INTO RAM
GETBS: LDY #0
STY VPCFLG ; INVALIDATE [VPC]
STY I+HI ; CLEAR MSB OF INDEX
STY MUL ; AND MULTIPLICATION
STY MUH ; REGISTERS
SEC
SBC #1 ; ZERO-ALIGN AND
ASL A ; WORD-ALIGN THE
ROL I+HI ; BLOCKSET INDEX (ALSO CLEARS CARRY)
ADC BTAB+LO ; ADD BASE ADDRESS OF
STA I+LO ; BLOCKSET TABLE
LDA I+HI ; TO GET ABS ADDR OF POINTER
ADC BTAB+HI ; INTO [I]
STA I+HI
LDA (I),Y ; GET MSB OF POINTER ([Y] = 0)
STA VPCH
INY ; ALSO GET LSB
LDA (I),Y ; SO THAT [VPC] POINTS TO
STA VPCL ; V-ADDR OF BLOCKSET FILE
;***
LDA #00
STA VPC0
;***
JSR GETBYT
STA BLKLEN ; SAVE # BYTES PER BLOCK
JSR GETBYT ; 2ND BYTE HAS # BLOCKS
STA BSIZE ; SAVE HERE FOR REFERENCE
STA MUSHFT ; AND HERE FOR MULTIPLY
LDA VPCL ; MOVE V-ADDR OF BLOCKSET DATA
STA BSADR+LO ; INTO [BSADR]
LDA VPCH
STA BSADR+HI
CMP IPURE ; IS THIS SET IN I-PRELOAD?
BCC GBLX ; EXIT NOW IF SO
; LOAD THE ENTIRE BLOCKSET AT [VPC] INTO PAGING RAM
LDY #7 ; INIT BIT-LOOP INDEX
LDX BLKLEN ; GET BLOCK LENGTH
DEX ; ZERO-ALIGN
GBL1: TXA ; MULTIPLY BY
LSR MUSHFT ; # BLOCKS IN BLOCKSET
BCC GBL2 ; TO GET SIZE
ADC MUH ; OF BLOCKSET
STA MUH ; IN [MUL/H]
GBL2: ROR MUH
ROR MUL
DEY
BPL GBL1
;***
LSR MUH
ROR MUL
;***
LDA VPCL ; ADD LSB OF BLOCKSET START ADDRESS
CLC ; TO LSB OF
ADC MUL ; BLOCKSET SIZE IN [MUL/H]
BCC GBL3 ; CONTINUE IF NO PAGE OVERFLOW
INC MUH ; ELSE FORCE EXTRA PAGE LOAD
GBL3: LDA MUH ; IF [MUH] = 0,
BEQ GBLX ; NO MORE PAGES ARE NEEDED
GBL4: INC VPCH ; ELSE POINT TO NEXT PAGE
LDA #0
STA VPCFLG ; INVALIDATE [VPC]
JSR GETBYT ; GET A BYTE (FORCE PAGE LOAD)
DEC MUH ; LOADED ALL BLOCKSET PAGES YET?
BNE GBL4 ; LOOP TILL EMPTY
LDA #0
STA VPCFLG ; INVALIDATE [VPC]
GBLX: RTS
; ---------------------------------
; GET BLOCK [A] IN CURRENT BLOCKSET
; ---------------------------------
; ENTRY: BLOCK ID # (0-255) IN [A]
; EXIT: BLOCK DATA IN [BLOCK]
GETBLK: STA MUSHFT ; SAVE BLOCK ID
LDA #0
STA VPCFLG ; INVALIDATE [VPC]
STA MUL ; CLEAR LSB AND
STA MUH ; MSB OF OFFSET
LDY #7 ; INIT BIT-SHIFT INDEX
LDX BLKLEN ; GET LENGTH OF BLOCKS
DEX ; ZERO-ALIGN
STX I+LO ; SAVE FOR LATER LOOPING
MULP: TXA
LSR MUSHFT
BCC MUSK
ADC MUH
STA MUH
MUSK: ROR MUH
ROR MUL
DEY
BPL MULP
;MUEND: LDA MUL ; [MUL/H] HAS BLOCK OFFSET
; CLC
; ADC BSADR+LO ; ADD THE VIRTUAL BASE ADDR
; STA VPCL ; OF THE CURRENT BLOCKSET
; LDA MUH ; TO GET THE VIRTUAL BASE ADDRESS
; ADC BSADR+HI ; OF THE DESIRED BLOCK
; STA VPCH
;***
MUEND: LDA BSADR+LO ; PUT WORD POINTER TO START OF BLOCKSET
STA VPCL ; IN VPCH,L
LDA BSADR+HI
STA VPCH
LDA #00 ; ZERO BOTTEM BIT
STA VPC0
LDA MUH ; ADD OFFSET TO BLOCK TO VPC
LDX MUL
JSR ADDVPC
;***
GBLL: JSR GETBYT ; GET A BYTE
LDX I+LO
STA BLOCK,X ; STORE BYTE IN [BLOCK]
DEC I+LO
DEX ; LOOP TILL
BPL GBLL ; ALL BYTES DONE
; NEGATE [BLOCK] IF [NEGATE] IS TRUE
LDA NEGATE
BEQ BLOCKX
LDX #7 ; NEGATE [BLOCK]
GBLLL: LDA BLOCK,X
EOR #$FF
STA BLOCK,X
DEX
BPL GBLLL
BLOCKX: RTS
; ------------------------
; SETUP FOR SETI AND SWAPI
; ------------------------
ISETUP: LDX ARG4+LO ; GET ADDR OF DESTINATION ICON
LDA ARG4+HI
CMP IPURE ; IS DEST IN I-PRELOAD?
BCC ISU ; CONTINUE IF SO
JMP PRERR2 ; ELSE PURITY VIOLATION!
;----------------------
; ENTRY FOR MASK SET UP
;----------------------
ISU: JSR GETI ; FETCH STATS OF DEST ICON
LDA IX1 ; COPY DEST ICON STATS
STA IX2 ; INTO AUXILIARY REGISTERS
LDA IY1
STA IY2
LDA IADR10
STA IADR20
LDA IADR1+LO
STA IADR2+LO
LDA IADR1+HI
STA IADR2+HI
LDX ARG3+LO ; NOW GET SOURCE ICON STATS
LDA ARG3+HI
; FALL THROUGH TO ...
; --------
; GET ICON
; --------
; ENTRY: V-ADDR OF ICON FILE IN [X/A]
; EXIT: ICON DATA V-ADDR IN [IADR1]
; X-SIZE IN [IX1] & [XDEX1]
; Y-SIZE IN [IY1] & [YDEX1]
; ASSIGNED BLOCKSET IN [BSET]
GETI: STX VPCL
STA VPCH
LDA #0
;***
STA VPC0
;***
STA VPCFLG ; INVALIDATE [VPC]
JSR GETBYT ; 1ST BYTE HAS
STA BSET ; ASSIGNED BLOCKSET
JSR GETBYT ; 2ND BYTE HAS
STA ITERS ; # ITERATIONS
JSR GETBYT ; 3RD BYTE HAS
STA IX1 ; X-SIZE
JSR GETBYT ; 4TH BYTE HAS
STA IY1 ; Y-SIZE
STA J+LO ; SAVE HERE FOR LATER
LDA VPCL ; SAVE BASE V-ADDR
STA IADR1+LO ; IN [IADR]
LDA VPCH
STA IADR1+HI
LDA VPC0
STA IADR10
CMP IPURE ; IS THIS ICON PRELOADED?
BCC NEWXY ; YES, SCRAM NOW
; MAKE SURE ICON DATA IS PAGED INTO RAM
LDA VPCL ; GET CURRENT PAGE POINTER
CLC
ADC IX1 ; ADD X-OFFSET
BCS ILD1 ; GET NEW PAGE IF BOUNDARY CROSSED
ILD0: DEC J+LO ; OUT OF X-LINES YET?
BEQ ILD2 ; YES, ICON IS ALL LOADED
ADC IX1 ; ELSE ADD ANOTHER X-LINE
BCC ILD0 ; LOOP BACK IF SAME PAGE
ILD1: STA J+HI ; SAVE NEW PAGE POINTER
INC VPCH ; POINT TO NEXT PAGE
LDA #0
STA VPCFLG ; INVALIDATE [VPC]
JSR GETBYT ; TO FORCE PAGE LOAD
LDA J+HI ; RESTORE POINTER
CLC ; CLEAR CARRY FOR NEW LOOP
BCC ILD0 ; BRANCH ALWAYS
ILD2: LDA #0
STA VPCFLG ; INVALIDATE [VPC]
; FALL THROUGH ...
; -------------------------
; REFRESH [XDEX1] & [YDEX1]
; -------------------------
NEWXY: LDA IX1
STA XDEX1
LDA IY1
STA YDEX1
RTS
; -----------------------------
; WILL SOURCE ICON FIT IN DEST?
; -----------------------------
; ENTRY: SOURCE STATS IN [1] REGISTERS, DEST IN [2]
; EXIT: CARRY CLEAR IF FIT OKAY, ELSE CARRY SET
; [IADR2] HAS ABSOLUTE ADDRESS OF SUB-ICON
DOFIT: LDA ARG1+LO ; GET X-POSITION
CLC
ADC IX1 ; ADD X-SIZE OF SOURCE
CMP IX2 ; COMPARE TO SIZE OF DEST
BCC FIT ; OKAY IF LESS
BNE FITEX ; OR EQUAL; ELSE EXIT W/CARRY SET
FIT: LDA ARG2+LO ; GET Y-POSITION
TAY ; SAVE HERE FOR INDEXING BELOW
CLC
ADC IY1 ; ADD SIZE OF SOURCE
CMP IY2 ; COMPARE TO SIZE OF DEST
BCC FIT0 ; OKAY IS LESS
BNE FITEX ; SO IS EQUAL; ELSE EXIT W/CARRY SET
; MAKE [IADR2] POINT TO ADDR OF SUB-ICON
FIT0: LDA ARG1+LO ; IF X-POS OF SUB-ICON IS 0,
BEQ FIT3 ; DON'T ADD X-OFFSET
; LDA IADR2+LO
; CLC
; ADC ARG1+LO ; ADD X-COORD OF SUB-ICON
; STA IADR2+LO ; TO BASE ADDR OF DEST ICON
; BCC FIT3 ; TO GET BASE ADDR OF SUB-ICON
; INC IADR2+HI
; BNE FIT3 ; ALWAYS SKIP 1ST Y-ITERATION
;***
LDA #0
LDX ARG1+LO
JSR ADDIA2
JMP FIT3
;***
;FIT2: LDA IADR2+LO ; ADD X-SIZE OF DEST ICON
; CLC ; TO BASE ADDR OF SUB-ICON
; ADC IX2 ; ONCE FOR EACH Y-COORD
; STA IADR2+LO
; BCC FIT3
; INC IADR2+HI
;***
FIT2: LDA #0
LDX IX2
JSR ADDIA2
;***
FIT3: DEY ; OUT OF Y-COORDS YET?
BPL FIT2 ; NO, KEEP ADDING
LDA IADR2+HI ; MAKE SUB-ICON ADDR ABSOLUTE
SEC ; BY STRIPPING OFF THE
SBC ISTART ; V-OFFSET
;***
LSR IADR20
ROL IADR2+LO
ROL A
;***
CLC ; AND ADDING THE ABS ADDR
ADC ICODE+HI ; OF THE
STA IADR2+HI ; I-PRELOAD (LSB NEEDN'T CHANGE)
CLC ; CLEAR CARRY FOR SUCCESS
FITEX: RTS
END

175
atari/iters.dip Normal file
View File

@@ -0,0 +1,175 @@
SBTTL "--- ITERATION STUFF ---"
;--------------------------------------------
; ITERATIONS
; EXECUTE THE ITERATION TABLE AT [ARG2]
; TEST FOR INPUT AFTER EACH ENTRY IS DONE AND
; -------------------------------------------
ITRATE: LDA ARG2+HI
STA ARG3+HI ; POINT ARG3 AT TABLE
LDA ARG2+LO
STA ARG3+LO
LDA #00 ; SET OFFSET INTO TABLE=0
STA ARG4+HI
STA ARG4+LO
JSR ICALC ; POINT [I] AT TABLE
LDA (I),Y ; NUMBER OF ENTRIES
STA ITICN
INY
LDA (I),Y ; ENTRY TO START WITH
STA ITPNT ; (NORMALLY ENTRY 1)
INC ARG4+LO ; POINT AT FISRT WORD IN FIRST ENTRY
LDX #1
ITLP2: CPX ITPNT ; SKIP ENTRIES 1 TO ITPNT
BEQ ITLOOP
JSR NXTENT
INX
BNE ITLP2 ; BRA
ITLOOP: JSR ICALC ; SET (I) CORECTLY
LDA (I),Y ; POINT IADR1 AT "HEADER"
STA IADR1+HI
STY IADR10
INY
LDA (I),Y
STA IADR1+LO
LDY #7 ; CURRENT ITERATION
LDA (I),Y
PHA ; SAVE
TAX
INX ; TAKE CARE OF SETING FOR NEXT ITERATION
LDY #9 ; NUMBER OF ITERATIONS
CMP (I),Y
BNE ITSKP2
LDX #1 ; RESTET TO FIRST ITERATION
ITSKP2: TXA
LDY #7
STA (I),Y ; NEXT ITERATION
INY ;=8
LDA (I),Y ; BSET
STA BSET
LDY #10 ; WIDTH
LDA (I),Y
STA IX1
TAX
INY
LDA (I),Y ; HEIGHT
STA IY1
TAY
JSR MULXY ; FIND WIDTH*HEIGHT
PLA ; RESTORE CURRENT ITERATION
TAY
ITLP3: DEY ; ZERO ALIGN FIRST TIME THRU/ THEN JUST DEX
BEQ ITSKP3
LDA MUH ; ADD LENGTH OF ICON (WIDTH*HEIGTH)
LDX MUL
JSR ADDIA1
JMP ITLP3
ITSKP3: TYA ;=0
LDX #4
JSR ADDIA1 ; SKIP 4 HEADER BYTES
LDY #2 ; =2
LDA (I),Y ; ICON XPOS
STA ARG1+HI
INY ; =3
LDA (I),Y
STA ARG1+LO
INY ; =4
LDA (I),Y ; ICON YPOS
STA ARG2+HI
INY ; =5
LDA (I),Y
STA ARG2+LO
INY ; =6
LDA (I),Y ; NEGATE
ITSKP4: STA NEGATE
LDA #00
STA MSKFLG ; DISABLE MASKING
JSR ITENT ; ENTER DRAW ROUTINE
JSR NXTENT ; POINT ARG4 AT NEXT ENTRY
LDX ITPNT ; ARE WE DONE YET?
CPX ITICN
BEQ ITEXI ; YES WE ARE DONE
INC ITPNT ; OTHERWISE POINT TO NEXT ENTRY
LDA VALUE+HI ; IF INPUT WAS CALLED WITH A NEG INT
BMI NONSNS ; DO NOT LOOK FOR INPUT
JSR SENSE ; DO WE HAVE AN INPUT
CMP #%10001111
BNE ITSKP5 ; GO HANDLE AN INPUT
NONSNS: JMP ITLOOP ; OTHERWISE DO NEXT ENTRY
ITSKP5: PHA ; SAVE INPUT
LDA #00
STA ARG4+HI
STA ARG4+LO ; POINT AT TABLE HEADER
JSR ICALC
INY ; =1
LDA ITPNT ; SAVE STATUS OF HOW FAR WE GOT IN DOING
STA (I),Y ; THE TABLE
PLA ; RESTORE SENSE
JMP PUTBYT ; RETURN SENSE
ITEXI: LDA #00
STA ARG4+HI
STA ARG4+LO
JSR ICALC ; POINT TO TABLE HEADER
INY ; =1
TYA
STA (I),Y
JMP NOIT
;-----------------------------
; SKIP 6 WORDS (1 TABLE ENTRY)
;-----------------------------
NXTENT: LDA #6 ; ADD 6 TO ARG4
CLC
ADC ARG4+LO
STA ARG4+LO
BCC NEXI
INC ARG4+HI
NEXI: RTS
;-----------------------------------------------------------
; ICALC POINTS [I] AT THE RAM ADDRESS OF THE TABLE,OFFSET OF
; ARG3,ARG4
; AND GENERATES A PURITY ERROR IF [I] POINTS AT PURE CODE.
;
; EXITS: <Y>=0
;------------------------------------------------------------
ICALC: LDY #00
LDA ARG4+LO
CLC
ADC ARG3+LO
STA I+LO
LDA ARG4+HI
ADC ARG3+HI
JMP ICENT ;ENTRY IN PCALC
END

576
atari/machine.dip Normal file
View File

@@ -0,0 +1,576 @@
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

538
atari/machine.src Normal file
View File

@@ -0,0 +1,538 @@
PAGE
SBTTL "--- MACHINE-DEPENDENT I/O: ATARI ---"
; ----------------------------
; FETCH ASCII KEYCODE INTO [A]
; ----------------------------
; EXIT: ASCII IN [A] & [IOCHAR]
BADKEY: JSR BOOP
JMP GKEY0
GETKEY: CLD
TXA ; SAVE [X] & [Y]
PHA
TYA
PHA
GKEY0: LDA #0
STA BLINK+LO ; LENGTHEN BLINK DELAY
STA BLINK+HI ; TO MAXIMUM
LDA COLCRS+LO ; CALC CURSOR X-POS
ASL A
ASL A
CLC
ADC #48
STA HPOSM0
LDA ROWCRS ; CALC CURSOR Y-POS
ASL A
ASL A
ASL A
CLC
ADC #39
TAY ; MOVE HERE FOR DRAWING
LDA #%00000011 ; FORCE CURSOR "ON"
STA CSHAPE
STA MISSL,Y ; AND DRAW IT
GKEY1: LDX CH ; CHECK HARDWARE FOR A KEYPRESS
INC BLINK+LO
BNE NOBLIN
INC BLINK+HI
BNE NOBLIN
LDA #$80
STA BLINK+HI ; RESET BLINK TIMER
LDA CSHAPE
EOR #%00000011
STA CSHAPE ; FLIP CURSOR SHAPE
STA MISSL,Y ; DRAW CURSOR INTO MISSILE RAM
NOBLIN: CPX #$FF ; KEY PRESSED?
BEQ GKEY1 ; NO, KEEP SCANNING
LDA #$FF
STA CH ; RESET KEY HARDWARE
TXA
BMI BADKEY ; REJECT CTRL KEYS
LDA ATASCI,X ; GET CODE INTO [A]
CMP #EOL ; WAS IT EOL?
BEQ CLICK ; OKAY IF SO
TAX ; ANY OTHER NEGATIVE CODE
BMI BADKEY ; IS ILLEGAL
; ERASE CURSOR, "CLICK" THE SPEAKER
CLICK: STA IOCHAR ; SAVE KEYCODE
LDA #0
STA MISSL,Y ; ERASE CURSOR
LDY #$80
CLK0: STY CONSOL
LDX #8
CLK1: DEX
BNE CLK1
DEY
BNE CLK0
PLA ; RESTORE
TAY ; EVERYTHING
PLA
TAX
LDA IOCHAR ; GET CHAR INTO [A]
RTS ; AND RETURN IT
; -----------------
; PRINT CHAR IN [A]
; -----------------
CHAR: STA IOCHAR ; SAVE HERE
TXA ; SAVE [X] AND [Y]
PHA
TYA
PHA
LDY ROWCRS ; Y-POS INTO [Y]
LDX COLCRS+LO ; X-POS INTO [X]
LDA IOCHAR ; RESTORE CHAR
CMP #EOL ; IS IT EOL?
BEQ OUTEOL ; YES, SPECIAL HANDLING
CMP #$0D ; ALSO CHECK FOR
BEQ OUTEOL ; ASCII EOL
; HANDLE A NON-EOL CHAR
CPY #YSIZE-1 ; ON LAST SCREEN LINE?
BCC NOSCRL ; NO, NO SCROLL NEEDED
CPX #XSIZE ; LAST CHAR ON LINE?
BCC NOSCRL ; NO, DON'T SCROLL
; SCROLL THE SCREEN
DOSCRL: DEY ; PUSH CURSOR UP ONE LINE
STY ROWCRS
LDX SLINE ; GET CURRENT SCROLL LINE
SRL0: CPX #YSIZE
BEQ SRL2 ; SCROLL DONE
LDA LOLINE,X ; GET ADDR OF DEST LINE
STA LTO+LO ; INTO [LTO]
LDA HILINE,X
STA LTO+HI
INX
LDA LOLINE,X ; GET ADDR OF SOURCE LINE
STA LFROM+LO ; INTO [LFROM]
LDA HILINE,X
STA LFROM+HI
LDY #XSIZE
SRL1: LDA (LFROM),Y ; MOVE SOURCE LINE
STA (LTO),Y ; TO DEST LINE
DEY
BPL SRL1
BMI SRL0 ; LOOP TILL [X] = YSIZE
SRL2: LDX #XSIZE
LDA #0
SRL3: STA SCREEN+920,X ; CLEAR LAST LINE
DEX ; OF SCREEN RAM
BPL SRL3
NOSCRL: LDA IOCHAR ; RESTORE CHAR
LDX #$0B ; CIO "PUT CHAR"
STX ICCOM ; COMMAND
LDX #0 ; IOCB #0 (E:)
STX ICBLEN+LO ; ZERO THE
STX ICBLEN+HI ; BUFFER LENGTH
JSR CIOV ; SEND IT OUT!
PLA ; RESTORE [X] AND [Y]
TAY
PLA
TAX
RTS
; HANDLE EOL
OUTEOL: LDA #$9B ; MAKE SURE [IOCHAR]
STA IOCHAR ; IS AN ATASCII EOL
CPY #YSIZE-1 ; LAST SCREEN LINE?
BCC NOSCRL ; NO, DON'T SCROLL
BCS DOSCRL ; ELSE SCROLL
; ---------------------
; FETCH A LINE OF INPUT
; ---------------------
; ENTRY: ABS ADDR OF READ BUFFER IN [ARG1]
; EXIT: # CHARS READ IN [A]
INPUT: JSR LINOUT ; FLUSH [LBUFF]
LDY #$FF
STY CH ; CLEAR KEYBOARD
INY ; = 0
STY LINCNT ; RESET LINE COUNT
INLOOP: JSR GETKEY ; GET ASCII INTO [A] AND [IOCHAR]
CMP #EOL ; EOL?
BEQ ENDLIN ; LINE DONE IF SO
CMP #BACKSP ; BACKSPACE?
BEQ BACKUP ; SPECIAL HANDLING
STA LBUFF,Y ; ELSE ADD CHAR TO INPUT BUFFER
INY ; NEXT POSITION IN LINE
SHOWIT: JSR CHAR ; SEND TO SCREEN
CPY #77 ; 2 SCREEN LINES FULL?
BCC INLOOP ; NO, GET ANOTHER CHAR
; HANDLE LINE OVERFLOW
NOMORE: JSR GETKEY
CMP #EOL ; IF EOL,
BEQ ENDLIN ; WRAP UP THE LINE
CMP #BACKSP ; BACKSPACE
BEQ BACKUP ; IS OKAY TOO
JSR BOOP ; ELSE COMPLAIN
JMP NOMORE ; AND INSIST
; HANDLE BACKSPACE
BACKUP: DEY ; BACK UP THE POINTER
BPL SHOWIT ; SEND BS IF NOT START OF LINE
JSR BOOP ; ELSE SCREAM WITH PAIN
LDY #0 ; RESET POINTER
BEQ INLOOP ; AND WAIT FOR SOMETHING BETTER
; HANDLE END OF LINE
ENDLIN: STA LBUFF,Y ; SHIP EOL TO BUFFER
INY ; UPDATE INDEX
STY LINLEN ; SAVE HERE FOR "READ"
STY PRLEN ; AND HERE FOR "PPRINT"
JSR CHAR ; AND SEND EOL TO SCREEN
; MOVE [LBUFF] TO [ARG1] W/LC CONVERSION
LEX0: LDA LBUFF-1,Y ; GET A CHAR FROM [LBUFF]
CMP #EOL ; ATASCII EOL?
BNE LEX1 ; IF SO,
LDA #$0D ; CONVERT TO ASCII
BNE LEX2
LEX1: CMP #'A' ; IF CHAR IS ALPHA,
BCC LEX2 ; CONVERT TO LOWER CASE
CMP #'Z'+1
BCS LEX2
ADC #$20
LEX2: STA (ARG1),Y ; MOVE CHAR TO INPUT BUFFER AT [ARG1]
DEY ; LOOP TILL
BPL LEX0 ; ALL CHARS MOVED
JSR PPRINT ; SCRIPT [LBUFF] IF ENABLED
LDA LINLEN ; RESTORE # CHARS
RTS ; INTO [A]
; -----------------------
; DIRECT PRINT LINE [X/A]
; -----------------------
; ENTRY: STRING ADDRESS IN [X/A] (LSB/MSB)
; STRING LENGTH IN [Y]
DLINE: STX STRING+LO ; DROP STRING ADDRESS
STA STRING+HI ; INTO DUMMY BYTES
LDX #0 ; INIT CHAR-FETCH INDEX
DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE
STRING: DW $0000 ; DUMMY OPERAND BYTES
JSR CHAR
INX
DEY ; LOOP TILL
BNE DOUT ; OUT OF CHARS
RTS
; -----------------------
; SEND [LBUFF] TO PRINTER
; -----------------------
; ENTRY: LENTH OF LINE IN [PRLEN]
PNAME: DB "P:" ; FILENAME FOR PRINTER
DB EOL
SFLAG: DB 0 ; PREVIOUS SCRIPTING STATE
PPRINT: LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED?
BEQ PEX ; NO, SCRAM IMMEDIATELY
LDA ZBEGIN+ZSCRIP+1 ; CHECK SCRIPT FLAG
AND #%00000001 ; SCRIPTING ON?
BEQ PEX ; NO, EXIT
LDA PSTAT ; CHECK PRINTER STATUS
BMI PEX ; CAN'T OPEN IF NEGATIVE
BNE PP1 ; ALREADY OPEN, SCRIPT THE LINE
; OPEN THE PRINTER FOR OUTPUT
JSR CLOSEP ; CLOSE IOCB #1 FIRST FOR SAFETY
LDX #$10 ; IOCB #1 (P:)
LDA #LOW PNAME ; POINT
STA ICBADR+LO,X ; TO
LDA #HIGH PNAME ; P:
STA ICBADR+HI,X ; FILENAME
LDA #$03 ; CIO "OPEN"
STA ICCOM,X ; COMMAND
LDA #$08 ; SET CHANNEL
STA ICAUX1,X ; FOR WRITE-ONLY
LDA #0
STA ICAUX2,X ; ZERO THIS BYTE
JSR CIOV ; OPEN IT!
TYA ; STATUS CODE IN [Y]
BMI BADP ; ERROR IF NEGATIVE
LDA #$70
STA POKMSK
STA IRQEN ; DISABLE BREAK KEY
LDA #1 ; SET [PSTAT]
STA PSTAT ; TO INDICATE "PRINTER READY"
; PRINT [LBUFF]
PP1: LDX #$10 ; IOCB #1 (P:)
LDA #LOW LBUFF ; TELL CIO
STA ICBADR+LO,X ; WHERE
LDA #HIGH LBUFF ; [LBUFF]
STA ICBADR+HI,X ; IS HIDING
LDA PRLEN ; # CHARS TO PRINT
STA ICBLEN+LO,X
LDA #0 ; CLEAR THE
STA ICBLEN+HI,X ; MSB OF LINE LENGTH
LDA #$0B ; CIO "PUT BUFFER" COMMAND (BM 4/9/85)
STA ICCOM,X ; COMMAND
JSR CIOV
TYA
BPL PEX ; EXIT IF NO ERROR
; HANDLE PRINTER ERROR
BADP: LDA #$FF ; SET PRINTER STATUS
STA PSTAT ; TO "CAN'T OPEN"
; CLOSE PRINTER CHANNEL (IOCB #1)
CLOSEP: LDX #$10 ; IOCB #1 (P:)
LDA #$0C ; CIO "CLOSE"
STA ICCOM,X ; COMMAND
JSR CIOV ; CLOSE THE CHANNEL
PEX: RTS
; ------------
; SPLIT SCREEN
; ------------
; SPLIT SCREEN AT LINE [ARG1]
; DISABLE SPLIT IF [ARG1] = 0
; IGNORE IF SPLIT ALREADY ENABLED OR [ARG1] >= 20
ZSPLIT: LDX ARG1+LO ; IF [ARG1] = 0,
BEQ OFFSPL ; TURN OFF SPLIT SCREEN
LDA SPSTAT ; SPLIT ALREADY ENABLED?
BNE SPLEX ; IGNORE REQUEST IF SO
CPX #20 ; IF [ARG1] >= 20,
BCS SPLEX ; IGNORE
INX
STX SLINE ; ELSE SET NEW SPLIT LINE
STX SPSTAT ; SET "SPLIT ENABLED" FLAG
SPL0: LDA LOLINE,X ; MAKE [LFROM] POINT TO
STA LFROM+LO ; LINE [X] IN WINDOW
LDA HILINE,X
STA LFROM+HI
LDY #XSIZE ; CLEAR LINE [X]
LDA #0
SPL1: STA (LFROM),Y
DEY
BPL SPL1
DEX ; DONE ALL LINES?
BNE SPL0 ; LOOP TILL WINDOW CLEARED
STX LINCNT ; RESET LINE COUNT TO ZERO
SPCALC: LDA #YSIZE-1 ; CALCULATE # LINES TO SCROLL
SEC ; BEFORE "MORE" APPEARS:
SBC SLINE ; LMAX = YSIZE-SLINE-1
STA LMAX
DEC LMAX
SPLEX: RTS
; --------------------
; DISABLE SPLIT SCREEN
; --------------------
OFFSPL: JSR TOBOT1 ; SET CURSOR TO BOTTOM
SPLOFF: LDX #1
STX SLINE ; SPLIT AT LINE 1
DEX ; = 0
STX SPSTAT ; TURN OFF STATUS FLAG
STX LINCNT ; RESET LINE COUNT
LDA #21
STA LMAX ; SET MAXIMUM LINE SCROLL
BNE NEWLOG ; RESET LINE MAP & RETURN
; ------
; SCREEN
; ------
; GO TO TOP WINDOW IF [A] = 0
; GO TO BOTTOM IF [A] = 1
; IGNORE IF SPLIT NOT ENABLED OR [A] <> 0 OR 1
ZSCRN: LDA SPSTAT ; IF SPLIT NOT ENABLED,
BEQ SPLEX ; IGNORE REQUEST
LDA ARG1+LO ; IF [ARG1] = 0,
ORA ARG1+HI
BEQ TOBOT0 ; GO TO BOTTOM WINDOW
CMP #1 ; IF [ARG1] <> 1,
BNE SPLEX ; IGNORE THE REQUEST
; SET TO TOP WINDOW
TOTOP: LDY #21 ; TEMPORARILY RESET
STY LMAX ; [LMAX] TO KILL "MORE"
LDY #1 ; Y-POS = 1
BNE DOSCRN
; SET TO BOTTOM WINDOW
TOBOT0: JSR SPCALC ; RE-CALC [LMAX]
TOBOT1: LDY #23 ; Y-POS = 23
DOSCRN: STY ROWCRS ; Y-POS = [Y]
LDA #0 ; X-POS = 0
STA COLCRS+LO
STA LINCNT ; RESET LINE COUNT
; FALL THROUGH ...
; ----------------------
; RESET LOGICAL LINE MAP
; ----------------------
NEWLOG: LDA #$FF
STA LOGMAP
STA LOGMAP+1
STA LOGMAP+2
RTS
; ---------
; RAZZ USER
; ---------
BOOP: LDA #200 ; SET
STA AUDF1 ; FREQUENCY
LDA #$AA ; PURE TONE, VOLUME #10
STA AUDC1
LDA #252 ; 4 JIFFY DELAY
STA RTCLOK
BOOP0: LDA RTCLOK
BNE BOOP0
STA AUDC1 ; SHUT OFF SOUND
RTS
; ------------
; CLEAR SCREEN
; ------------
CLS: LDA #LOW SCREEN
STA I+LO
LDA #HIGH SCREEN ; POINT [I] TO
STA I+HI ; SCREEN RAM
LDA #0
STA LENGTH ; RESET LINE LENGTH
TAY
LDX #4 ; CLEAR 4 PAGES
CLS0: STA (I),Y ; FOR SCREEN
INY
BNE CLS0
INC I+HI ; POINT TO NEXT PAGE
DEX ; 4 PAGES DONE?
BNE CLS0 ; LOOP TILL EMPTY
LDY #1 ; SET Y-POS TO 1
STY ROWCRS
DEY ; X-POS TO 0
STY COLCRS+LO
JMP SPLOFF ; DISABLE SPLIT-SCREEN & RETURN
; -------------------
; LINE ADDRESS TABLES
; -------------------
LOLINE: DB $40,$68,$90,$B8,$E0,$08,$30,$58
DB $80,$A8,$D0,$F8,$20,$48,$70,$98
DB $C0,$E8,$10,$38,$60,$88,$B0,$D8
HILINE: DB $BC,$BC,$BC,$BC,$BC,$BD,$BD,$BD
DB $BD,$BD,$BD,$BD,$BE,$BE,$BE,$BE
DB $BE,$BE,$BF,$BF,$BF,$BF,$BF,$BF
; ------------------------
; ATASCII CONVERSION TABLE
; ------------------------
ATASCI: DB $6C,$6A,$3B,$FF,$FF,$6B,$FF,$FF ; UNSHIFTED
DB $6F,$FF,$70,$75,$9B,$69,$2D,$FF
DB $76,$FF,$63,$FF,$FF,$62,$78,$7A
DB $34,$FF,$33,$36,$FF,$35,$32,$31
DB $2C,$20,$2E,$6E,$FF,$6D,$2F,$FF
DB $72,$FF,$65,$79,$FF,$74,$77,$71
DB $39,$FF,$30,$37,$7E,$38,$FF,$FF
DB $66,$68,$64,$FF,$FF,$67,$73,$61
DB $4C,$4A,$3A,$FF,$FF,$4B,$FF,$FF ; SHIFTED
DB $4F,$FF,$50,$55,$9B,$49,$2D,$FF
DB $56,$FF,$43,$FF,$FF,$42,$58,$5A
DB $24,$FF,$23,$36,$FF,$35,$22,$21
DB $2C,$20,$2E,$4E,$FF,$4D,$3F,$FF
DB $52,$FF,$45,$59,$FF,$54,$57,$51
DB $39,$FF,$30,$27,$7E,$38,$FF,$FF
DB $46,$48,$44,$FF,$FF,$47,$53,$41
END

216
atari/main.dip Normal file
View File

@@ -0,0 +1,216 @@
PAGE
SBTTL "--- MAIN LOOP ---"
MLOOP: LDX #$FF ; RESET THE
TXS ; HARDWARE STACK
INX ; = 0
STX NARGS ; CLEAR # ARGS
JSR NEXTPC ; GET Z-BYTE INTO [A]
STA OPCODE ; FLAGS ARE SET
IF DEBUG
LDA #0 ; BREAKPOINT #0
JSR DOBUG
LDA OPCODE
ENDIF
; DECODE AN OPCODE
TAX ; SET FLAGS
BMI DC0 ; IF POSITIVE,
JMP OP2 ; IT'S A 2-OP
DC0: CMP #$E0 ; IS IT "CALL"?
BNE DC1
JMP GCALL
DC1: CMP #$B0
BCS DC2
JMP OP1 ; OR MAYBE A 1-OP
DC2: CMP #$C0
BCS OPEXT
JMP OP0 ; PERHAPS A 0-OP
; --------------
; HANDLE AN X-OP
; --------------
OPEXT: JSR NEXTPC ; GRAB ARGUMENT BYTE
STA ABYTE ; HOLD IT HERE
LDX #0
STX ADEX ; INIT LOOP INDEX
BEQ OPX1 ; JUMP INTO LOOP
TOPX: LDA ABYTE ; GET ARG BYTE
ASL A ; SHIFT NEXT 2 ARG BITS
ASL A ; INTO BITS 7 & 6
STA ABYTE ; HOLD FOR LATER
OPX1: AND #%11000000 ; MASK OUT GARBAGE BITS
BNE OPX2
JSR GETLNG ; 00 = LONG IMMEDIATE
JMP OPXNXT
OPX2: CMP #%01000000 ; IS IT A SHORT IMMEDIATE?
BNE OPX3 ; NO, KEEP GUESSING
JSR GETSHT ; 01 = SHORT IMMEDIATE
JMP OPXNXT
OPX3: CMP #%10000000 ; LAST TEST
BNE OPX4 ; 11 = NO MORE ARGUMENTS
JSR GETVAR ; 10 = VARIABLE
OPXNXT: LDX ADEX ; ARGUMENT INDEX
LDA VALUE+LO ; GRAB LSB OF VALUE
STA ARG1+LO,X ; STORE IN ARGUMENT TABLE
LDA VALUE+HI ; GRAB MSB OF VALUE
STA ARG1+HI,X ; STORE THAT, TOO
INC NARGS ; UPDATE ARGUMENT COUNTER
INX
INX
STX ADEX ; UPDATE INDEX
CPX #8 ; DONE 4 ARGUMENTS YET?
BCC TOPX ; NO, GET SOME MORE
; ALL X-OP ARGUMENTS READY
OPX4: LDA OPCODE ; IS THIS
CMP #$E0 ; AN EXTENDED 2-OP?
BCS DOXOP ; NO, IT'S A REAL X-OP
JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP
DOXOP: LDX #LOW OPTX ; GET ADDR OF X-OP TABLE
LDY #HIGH OPTX ; INTO [X/Y]
AND #%00011111 ; ISOLATE OP ID BITS
CMP #NOPSX ; IS IT A LEGAL X-OP?
BCC DODIS ; YUP; TIME TO DISPATCH IT
; *** ERROR #2: UNDEFINED X-OP ***
LDA #2
JMP GERROR
; ---------------
; OPCODE DISPATCH
; ---------------
; ENTRY: MASKED OPCODE INDEX IN [A]
; OP-TABLE ADDR IN X/Y (LSB/MSB)
DODIS: STX I+LO ; SAVE TABLE ADDRESS
STY I+HI ; IN A POINTER
ASL A ; WORD-ALIGN THE OP INDEX
TAY
LDA (I),Y ; GET LSB OF DISPATCH ADDRESS
STA GO+LO ; INSTALL AS JSR OPERAND
INY
LDA (I),Y ; SAME WITH MSB
STA GO+HI
DB $20 ; 6502 "JSR" OPCODE
GO: DW $0000 ; DUMMY OPERAND BYTES
JMP MLOOP ; GO BACK FOR ANOTHER OPCODE
; -------------
; HANDLE A 0-OP
; -------------
OP0: LDX #LOW OPT0 ; GET ADDR OF 0-OP TABLE
LDY #HIGH OPT0 ; INTO [X/Y]
AND #%00001111 ; ISOLATE OP ID BITS
CMP #NOPS0 ; OUT OF RANGE?
BCC DODIS ; NO, DISPATCH
; *** ERROR #3: UNDEFINED 0-OP ***
LDA #3
JMP GERROR
; -------------
; HANDLE A 1-OP
; -------------
OP1: AND #%00110000 ; ISOLATE ARGUMENT BITS
BNE OP1A
JSR GETLNG ; 00 = LONG IMMEDIATE
JMP OP1EX
OP1A: CMP #%00010000 ; TEST AGAIN
BNE OP1B
JSR GETSHT ; 01 = SHORT IMMEDIATE
JMP OP1EX
OP1B: CMP #%00100000 ; ONE MORE TEST
BNE BADOP1 ; UNDEFINED STATE!
JSR GETVAR ; 10 = VARIABLE
OP1EX: JSR V2A1 ; VALUE TO [ARG1], UPDATE COUNT
LDX #LOW OPT1 ; LSB OF DISPATCH TABLE
LDY #HIGH OPT1 ; MSB
LDA OPCODE ; RESTORE OPCODE
AND #%00001111 ; ISOLATE OP ID BITS
CMP #NOPS1 ; IF WITHIN RANGE,
BCC DODIS ; EXECUTE THE 1-OP
; *** ERROR #4: UNDEFINED 1-OP ***
BADOP1: LDA #4
JMP GERROR
; -------------
; HANDLE A 2-OP
; -------------
OP2: AND #%01000000 ; ISOLATE 1ST ARG BIT
BNE OP2A
JSR GETSHT ; 0 = SHORT IMMEDIATE
JMP OP2B
OP2A: JSR GETVAR ; 1 = VARIABLE
OP2B: JSR V2A1 ; VALUE TO [ARG1], UPDATE COUNT
LDA OPCODE ; RESTORE OPCODE BYTE
AND #%00100000 ; ISOLATE 2ND ARG BIT
BNE OP2C
JSR GETSHT ; 0 = SHORT IMMEDIATE
JMP OP2D
OP2C: JSR GETVAR ; 1 = VARIABLE
OP2D: LDA VALUE+LO ; MOVE VALUE TO [ARG2]
STA ARG2+LO
LDA VALUE+HI
STA ARG2+HI
INC NARGS ; UPDATE COUNT
; ENTRY FOR EXTENDED 2-OPS
OP2EX: LDX #LOW OPT2 ; LSB OF DISPATCH TABLE
LDY #HIGH OPT2 ; MSB
LDA OPCODE ; RESTORE OPCODE BYTE
AND #%00011111 ; ISOLATE OP ID BITS
CMP #NOPS2
BCS BADOP2 ; ERROR IF OUT OF RANGE
JMP DODIS ; ELSE DISPATCH
; *** ERROR #5: UNDEFINED 2-OP ****
BADOP2: LDA #5
JMP GERROR
; --------------------------------------
; MOVE [VALUE] TO [ARG1], UPDATE [NARGS]
; --------------------------------------
V2A1: LDA VALUE+LO
STA ARG1+LO
LDA VALUE+HI
STA ARG1+HI
INC NARGS
RTS
END

212
atari/main.src Normal file
View File

@@ -0,0 +1,212 @@
PAGE
SBTTL "--- MAIN LOOP ---"
MLOOP: LDA #0
STA NARGS ; RESET # ARGUMENTS
JSR NEXTPC ; GET NEXT INSTRUCTION INTO [A]
STA OPCODE ; SAVE IT HERE
IF DEBUG
LDA SECTOR+LO
STA MBYTE
LDA #0 ; BREAKPOINT #0
JSR DOBUG
LDA OPCODE
ENDIF
; DECODE AN OPCODE
TAX ; SET FLAGS
BMI DC0 ; IF POSITIVE,
JMP OP2 ; IT'S A 2-OP
DC0: CMP #$B0
BCS DC1
JMP OP1 ; OR MAYBE A 1-OP
DC1: CMP #$C0
BCS OPEXT
JMP OP0 ; PERHAPS A 0-OP
; --------------
; HANDLE AN X-OP
; --------------
OPEXT: JSR NEXTPC ; GRAB THE ARGUMENT ID BYTE
STA ABYTE ; HOLD IT HERE
LDX #0
STX ADEX ; INIT ARGUMENT INDEX
BEQ OPX1 ; JUMP TO TOP OF LOOP
OPX0: LDA ABYTE ; GET ARG BYTE
ASL A ; SHIFT NEXT 2 ARG BITS
ASL A ; INTO BITS 7 & 6
STA ABYTE ; HOLD FOR LATER
OPX1: AND #%11000000 ; MASK OUT GARBAGE BITS
BNE OPX2
JSR GETLNG ; 00 = LONG IMMEDIATE
JMP OPXNXT
OPX2: CMP #%01000000 ; IS IT A SHORT IMMEDIATE?
BNE OPX3 ; NO, KEEP GUESSING
JSR GETSHT ; 01 = SHORT IMMEDIATE
JMP OPXNXT
OPX3: CMP #%10000000 ; LAST TEST
BNE OPX4 ; 11 = NO MORE ARGUMENTS
JSR GETVAR ; 10 = VARIABLE
OPXNXT: LDX ADEX ; RETRIEVE ARGUMENT INDEX
LDA VALUE+LO ; GRAB LSB OF VALUE
STA ARG1+LO,X ; STORE IN ARGUMENT TABLE
LDA VALUE+HI ; GRAB MSB OF VALUE
STA ARG1+HI,X ; STORE THAT, TOO
INC NARGS ; UPDATE ARGUMENT COUNTER
INX
INX
STX ADEX ; UPDATE INDEX
CPX #8 ; DONE 4 ARGUMENTS YET?
BCC OPX0 ; NO, GET SOME MORE
; ALL X-OP ARGUMENTS READY
OPX4: LDA OPCODE ; IS THIS
CMP #$E0 ; AN EXTENDED 2-OP?
BCS DOXOP ; NO, IT'S A REAL X-OP
JMP OP2EX ; ELSE TREAT IT LIKE A 2-OP
DOXOP: LDX #LOW OPTX ; GET ADDR OF X-OP TABLE
LDY #HIGH OPTX ; INTO [X/Y]
AND #%00011111 ; ISOLATE OP ID BITS
CMP #NOPSX ; IS IT A LEGAL X-OP?
BCC DODIS ; YUP; TIME TO DISPATCH IT
; *** ERROR #1 -- ILLEGAL X-OP ***
LDA #1
JMP ZERROR
; ---------------
; OPCODE DISPATCH
; ---------------
; ENTRY: MASKED OPCODE INDEX IN [A]
; OP-TABLE ADDR IN X/Y (LSB/MSB)
DODIS: STX I+LO ; SAVE TABLE ADDRESS
STY I+HI ; IN A POINTER
ASL A ; WORD-ALIGN THE OP INDEX
TAY
LDA (I),Y ; GET LSB OF DISPATCH ADDRESS
STA GO+LO ; INSTALL AS JSR OPERAND
INY
LDA (I),Y ; SAME WITH MSB
STA GO+HI
DB $20 ; 6502 "JSR" OPCODE
GO: DW $0000 ; DUMMY OPERAND BYTES
JMP MLOOP ; GO BACK FOR ANOTHER OPCODE
; -------------
; HANDLE A 0-OP
; -------------
OP0: LDX #LOW OPT0 ; GET 0-OP TABLE ADDR
LDY #HIGH OPT0 ; INTO [X/Y]
AND #%00001111 ; ISOLATE 0-OP ID BITS
CMP #NOPS0 ; OUT OF RANGE?
BCC DODIS ; NO, DISPATCH IT
; *** ERROR #2 -- ILLEGAL 0-OP ***
LDA #2
JMP ZERROR
; -------------
; HANDLE A 1-OP
; -------------
OP1: AND #%00110000 ; ISOLATE ARGUMENT BITS
BNE OP1A
JSR GETLNG ; 00 = LONG IMMEDIATE
JMP OP1EX
OP1A: CMP #%00010000 ; TEST AGAIN
BNE OP1B
JSR GETSHT ; 01 = SHORT IMMEDIATE
JMP OP1EX
OP1B: CMP #%00100000 ; ONE MORE TEST
BNE BADOP1 ; UNDEFINED STATE!
JSR GETVAR ; 10 = VARIABLE
OP1EX: JSR V2A1 ; MOVE [VALUE] TO [ARG1], UPDATE [NARGS]
LDX #LOW OPT1 ; GET ADDR OF 1-OP TABLE
LDY #HIGH OPT1 ; INTO [X/Y]
LDA OPCODE ; RESTORE OPCODE
AND #%00001111 ; ISOLATE OP ID BITS
CMP #NOPS1 ; IF WITHIN RANGE,
BCC DODIS ; EXECUTE THE 1-OP
; *** ERROR #3 -- ILLEGAL 1-OP ***
BADOP1: LDA #3
JMP ZERROR
; -------------
; HANDLE A 2-OP
; -------------
OP2: AND #%01000000 ; ISOLATE 1ST ARG BIT
BNE OP2A
JSR GETSHT ; 0 = SHORT IMMEDIATE
JMP OP2B
OP2A: JSR GETVAR ; 1 = VARIABLE
OP2B: JSR V2A1 ; [VALUE] TO [ARG1], UPDATE [NARGS]
LDA OPCODE ; RESTORE OPCODE BYTE
AND #%00100000 ; ISOLATE 2ND ARG BIT
BNE OP2C
JSR GETSHT ; 0 = SHORT IMMEDIATE
JMP OP2D
OP2C: JSR GETVAR ; 1 = VARIABLE
OP2D: LDA VALUE+LO ; MOVE 2ND [VALUE]
STA ARG2+LO ; INTO [ARG2]
LDA VALUE+HI
STA ARG2+HI
INC NARGS ; UPDATE ARGUMENT COUNT
; EXECUTE A 2-OP OR EXTENDED 2-OP
OP2EX: LDX #LOW OPT2 ; LSB OF DISPATCH TABLE
LDY #HIGH OPT2 ; MSB
LDA OPCODE ; RESTORE OPCODE BYTE
AND #%00011111 ; ISOLATE OP ID BITS
CMP #NOPS2
BCS BADOP2 ; ERROR IF OUT OF RANGE
JMP DODIS ; ELSE DISPATCH
; *** ERROR #4 -- ILLEGAL 2-OP ****
BADOP2: LDA #4
JMP ZERROR
; --------------------------------------
; MOVE [VALUE] TO [ARG1], UPDATE [NARGS]
; --------------------------------------
V2A1: LDA VALUE+LO
STA ARG1+LO
LDA VALUE+HI
STA ARG1+HI
INC NARGS
RTS
END

160
atari/objects.src Normal file
View File

@@ -0,0 +1,160 @@
PAGE
SBTTL "--- OBJECT & PROPERTY HANDLERS ---"
; ----------------------------------
; GET ABSOLUTE ADDRESS OF OBJECT [A]
; ----------------------------------
; EXIT: ADDRESS IN [I]
OBJLOC: STA I+LO ; SAVE LSB FOR ADDING
LDX #0 ; CLEAR MSB
STX I+HI ; FOR SHIFTING
ASL A ; MULTIPLY BY 8
ROL I+HI
ASL A
ROL I+HI
ASL A
ROL I+HI
CLC ; ADD TO ITSELF
ADC I+LO ; TO GET TIMES 9
BCC OBJ1
INC I+HI
OBJ1: CLC
ADC #53 ; NOW ADD 53
BCC OBJ2 ; (THE OBJECT TABLE OFFSET)
INC I+HI
OBJ2: CLC ; NEXT ADD THE ABS ADDR
ADC OBJTAB+LO ; OF THE OBJECT TABLE
STA I+LO
LDA I+HI
ADC OBJTAB+HI
STA I+HI
RTS
; -----------------------------
; GET ADDRESS OF PROPERTY TABLE
; -----------------------------
; EXIT: [I] HAS ABSOLUTE ADDR OF PROPERTY TABLE
; [Y] HAS OFFSET TO START OF PROP IDS
PROPB: LDA ARG1+LO
JSR OBJLOC
LDY #7
LDA (I),Y ; GET MSB OF P-TABLE ADDRESS
CLC
ADC ZCODE ; MAKE IT ABSOLUTE
TAX ; AND SAVE HERE
INY
LDA (I),Y ; NOW GET LSB
STA I+LO
STX I+HI ; [I] NOW POINTS TO PROP TABLE
LDY #0
LDA (I),Y ; GET LENGTH OF SHORT DESC
ASL A ; WORD-ALIGN IT
TAY ; EXPECTED HERE
INY ; POINT JUST PAST THE DESCRIPTION
RTS
; -------------------
; FETCH A PROPERTY ID
; -------------------
; ENTRY: LIKE "PROPB" EXIT
PROPN: LDA (I),Y
AND #%00011111 ; MASK OUT LENGTH BITS
RTS
; -------------------------------
; FETCH # BYTES IN PROPERTY VALUE
; -------------------------------
; ENTRY: LIKE "PROPB" EXIT
PROPL: LDA (I),Y
LSR A ; LENGTH IS IN
LSR A ; BITS 7-5
LSR A ; SO SHIFT INTO PLACE
LSR A
LSR A
RTS
; ----------------------
; POINT TO NEXT PROPERTY
; ----------------------
; ENTRY: LIKE "PROPB" EXIT
PROPNX: JSR PROPL ; GET LENGTH OF CURRENT PROP
TAX ; SAVE HERE
PPX: INY ; LOOP UNTIL
DEX ; [Y] POINTS TO
BPL PPX ; START OF NEXT PROP
INY ; CORRECT ALIGNMENT
RTS
; ----------------
; GET OBJECT FLAGS
; ----------------
; ENTRY: OBJECT # IN [ARG1], FLAG # IN [ARG2]
; EXIT: FLAG WORD IN [K], BIT ID IN [J],
; FLAG WORD ADDRESS IN [I]
FLAGSU: LDA ARG1+LO
JSR OBJLOC ; GET OBJECT ADDR IN [I]
LDA ARG2+LO ; LOOK AT FLAG ID
CMP #$10 ; FIRST SET OF FLAGS?
BCC FLS1 ; YES, ADDR IN [I] IS CORRECT
SBC #16 ; ELSE ZERO-ALIGN FLAG INDEX
TAX ; SAVE IT HERE
LDA I+LO ; ADD 2 TO ADDRESS IN [I]
CLC ; TO POINT TO ADDRESS OF
ADC #2 ; 2ND FLAG WORD
STA I+LO
BCC FLS0
INC I+HI
FLS0: TXA ; RESTORE INDEX
FLS1: STA K+LO ; SAVE FLAG ID HERE
LDX #1 ; INIT THE
STX J+LO ; FLAG WORD TO
DEX ; $0001
STX J+HI
LDA #15 ; SUBTRACT THE BIT POSITION
SEC ; FROM 15
SBC K+LO ; TO GET THE SHIFT LOOP
TAX ; INDEX
BEQ FLS2 ; EXIT NOW IF NO SHIFT NEEDED
FLSL: ASL J+LO ; SHIFT THE BIT
ROL J+HI ; INTO POSITION
DEX
BNE FLSL
FLS2: LDY #0 ; MOVE THE FLAG WORD
LDA (I),Y ; INTO [J]
STA K+HI ; FIRST THE MSB
INY
LDA (I),Y
STA K+LO ; THEN THE LSB
RTS
END

45
atari/ops0.dip Normal file
View File

@@ -0,0 +1,45 @@
PAGE
SBTTL "--- 0-OPS ---"
; -----
; RTRUE
; -----
; SIMULATE "RETURN 1"
GRTRUE: LDX #1
GRT1: LDA #0
GRT2: STX ARG1+LO
STA ARG1+HI
JMP GRET
; ------
; RFALSE
; ------
; SIMULATE "RETURN 0"
GRFALS: LDX #0
BEQ GRT1
; ------
; RSTACK
; ------
; "RETURN" WITH VALUE ON STACK
GRSTAK: JSR POPVAL ; GET VALUE INTO [X/A]
JMP GRT2
; ------
; FSTACK
; ------
; FLUSH TOP VALUE OFF G-STACK
GFSTAK EQU POPVAL
END

160
atari/ops0.src Normal file
View File

@@ -0,0 +1,160 @@
PAGE
SBTTL "--- 0-OPS ---"
; -----
; RTRUE
; -----
; SIMULATE A "RETURN 1"
ZRTRUE: LDX #1
ZRT0: LDA #0
ZRT1: STX ARG1+LO ; GIVE TO
STA ARG1+HI ; [ARG1]
JMP ZRET ; AND DO THE RETURN
; ------
; RFALSE
; ------
; SIMULATE A "RETURN 0"
ZRFALS: LDX #0
BEQ ZRT0
; ------
; PRINTI
; ------
; PRINT Z-STRING FOLLOWING THE OPCODE
ZPRI: LDA ZPCH ; MOVE [ZPC] INTO [MPC]
STA MPCH
LDA ZPCM
STA MPCM
LDA ZPCL
STA MPCL
LDA #0
STA MPCFLG ; [MPC] NO LONGER VALID
JSR PZSTR ; PRINT THE Z-STRING AT [MPC]
LDX #5 ; COPY STATE OF [MPC]
PRIL: LDA MPC,X ; INTO [ZPC]
STA ZPC,X
DEX
BPL PRIL
RTS
; ------
; PRINTR
; ------
; DO A "PRINTI," FOLLOWED BY "CRLF" AND "RTRUE"
ZPRR: JSR ZPRI
JSR ZCRLF
JMP ZRTRUE
; ------
; RSTACK
; ------
; "RETURN" WITH VALUE ON STACK
ZRSTAK: JSR POPVAL ; GET VALUE INTO [X/A]
JMP ZRT1 ; AND GIVE IT TO "RETURN"
; ------
; VERIFY
; ------
; VERIFY GAME CODE ON DISK
ZVER: JSR VERNUM ; DISPLAY VERSION NUMBER, GET SIDE 1
LDX #3
LDA #0
ZVR: STA J+LO,X ; CLEAR [J], [K]
STA MPC,X ; [MPC] AND [MPCFLG]
DEX
BPL ZVR
LDA #64 ; POINT [MPC] TO Z-ADDRESS $00040
STA MPCL ; 1ST 64 BYTES AREN'T CHECKED
LDA #K+HI ; PATCH THE "GETBYT" ROUTINE
STA PATCH ; TO USE [K+HI]=0 INSTEAD OF [ZPURE]
LDA ZBEGIN+ZENDLD ; GET LAST BYTE OF ENDLOAD
STA I+HI ; FIRST MSB
LDA ZBEGIN+ZENDLD+1
STA I+LO ; THEN LSB
; CHECKSUM THE PRELOAD (SIDE 1)
VSUM: JSR GETBYT ; GET A Z-BYTE INTO [A]
CLC
ADC J+LO ; ADD IT TO SUM
STA J+LO ; IN [J]
BCC VSUM0
INC J+HI
VSUM0: LDA MPCL ; END OF Z-CODE YET?
CMP I+LO ; CHECK LSB
BNE VSUM
LDA MPCM ; AND MIDDLE BYTE
CMP I+HI ; (HIGH BIT NEEDN'T BE CHECKED)
BNE VSUM
; CHECKSUM "PURE" CODE (SIDE 2)
JSR SIDE2 ; PROMPT FOR SIDE 2
LDA ZBEGIN+ZLENTH ; GET MSB
STA I+HI ; AND
LDA ZBEGIN+ZLENTH+1 ; LSB OF Z-CODE LENGTH IN BYTES
ASL A ; MULTIPLY BY
STA I+LO ; TWO
ROL I+HI ; TO GET # BYTES
ROL K+LO ; IN GAME
VSUM2: JSR GETBYT ; GET A Z-BYTE INTO [A]
CLC
ADC J+LO ; ADD IT TO SUM
STA J+LO ; IN [J]
BCC VSUM3
INC J+HI
VSUM3: LDA MPCL ; END OF Z-CODE YET?
CMP I+LO ; CHECK LSB
BNE VSUM2
LDA MPCM ; MIDDLE BYTE
CMP I+HI
BNE VSUM2
LDA MPCH ; AND HIGH BIT
CMP K+LO
BNE VSUM2
LDA #ZPURE ; UNPATCH "GETBYT"
STA PATCH
LDA ZBEGIN+ZCHKSM+1 ; GET LSB OF CHECKSUM
CMP J+LO ; DOES IT MATCH?
BNE BADVER ; NO, PREDICATE FAILS
LDA ZBEGIN+ZCHKSM ; ELSE CHECK MSB
CMP J+HI ; LOOK GOOD?
BNE BADVER ; IF MATCHED,
JMP PREDS ; GAME IS OKAY
BADVER: JMP PREDF
END

154
atari/ops1.dip Normal file
View File

@@ -0,0 +1,154 @@
PAGE
SBTTL "--- 1-OPS ---"
; ----
; PUSH
; ----
; PUSH [ARG1] ONTO G-STACK
GPUSH: LDX ARG1+LO
LDA ARG1+HI
JMP PSHXA
; ---
; POP
; ---
; POP Z-STACK INTO VARIABLE [ARG1]
GPOP: JSR POPVAL
JMP DOPUT
; -----
; VALUE
; -----
; RETURN VALUE OF VARIABLE [ARG1]
GVALUE: LDA ARG1+LO ; GET VARIABLE ID
JSR VARGET ; PUT VALUE INTO [VALUE]
JMP PUTVAL
; ---
; INC
; ---
; INCREMENT VARIABLE [ARG1]
GINC: LDA ARG1+LO
JSR VARGET
JSR INCVAL
JMP DOPUT
; ---
; DEC
; ---
; DECREMENT VARIABLE [ARG1]
GDEC: LDA ARG1+LO
JSR VARGET
JSR DECVAL
DOPUT: LDA ARG1+LO
JMP VARPUT
; -----
; ZERO?
; -----
; [ARG1] = 0 ?
GZEROP: LDA ARG1+LO
ORA ARG1+HI
BEQ PYES
JMP PREDF
PYES: JMP PREDS
; ----
; BNOT
; ----
; COMPLEMENT [ARG1]
GBNOT: LDA ARG1+LO
EOR #$FF
TAX
LDA ARG1+HI
EOR #$FF
JMP VEXIT
; ----
; JUMP
; ----
; JUMP TO G-ADDRESS [ARG1]
GJUMP: JSR A12VAL ; MOVE [ARG1] TO [VALUE]
JMP PREDB3 ; A BRANCH THAT ALWAYS SUCCEEDS
; ------
; RETURN
; ------
; RETURN FROM "CALL" WITH VALUE [ARG1]
GRET: LDA OLDGSP
STA GSP ; SYNC THE G-STACK
JSR POPVAL ; POP # LOCALS INTO [X]
TXA ; ANY LOCALS?
BEQ RET2 ; NO, SKIP
; RESTORE ALL PUSHED LOCALS
ASL A ; WORD-ALIGN # LOCALS
STA ADEX ; USE FOR INDEXING
DEC ADEX ; ZERO-ALIGN THE INDEX
RET1: JSR POPVAL ; POP LOCAL INTO [X/A] AND [VALUE]
LDX ADEX ; GET INDEX
STA LOCALS,X ; STORE MSB IN TABLE
DEX
LDA VALUE+LO ; SAME FOR LSB
STA LOCALS,X
DEX
STX ADEX ; SAVE INDEX
BPL RET1 ; LOOP TILL EMPTY
; RESTORE GPC
RET2: JSR POPVAL ; RESTORE [GPC]
;***
STX GPC0 ; DON'T FORGET THAT 17TH BIT
JSR POPVAL
;***
STX GPCL
STA GPCH
LDA #0
STA GPCFLG ; PC HAS CHANGED
JSR POPVAL
STX OLDGSP ; RESTORE OLD GSP
LDX ARG1+LO
LDA ARG1+HI
; FALL THROUGH TO ...
; -----------------
; VALUE RETURN EXIT
; -----------------
; ENTRY: VALUE IN [X/A] (LSB/MSB)
VEXIT: STX VALUE+LO
STA VALUE+HI
JMP PUTVAL
END

303
atari/ops1.src Normal file
View File

@@ -0,0 +1,303 @@
PAGE
SBTTL "--- 1-OPS ---"
; -----
; ZERO?
; -----
; [ARG1] = 0?
ZZERO: LDA ARG1+LO
ORA ARG1+HI
BEQ PFINE
PYUCK: JMP PREDF
; -----
; NEXT?
; -----
; RETURN "NEXT" POINTER IN OBJECT [ARG1];
; FAIL IF LAST AND RETURN ZERO
ZNEXT: LDA ARG1+LO
JSR OBJLOC ; GET OBJECT ADDR INTO [I]
LDY #5 ; POINT TO "NEXT" SLOT
BNE FIRST1
; ------
; FIRST?
; ------
; RETURN "FIRST" POINTER IN OBJECT [ARG1];
; FAIL IF LAST AND RETURN ZERO
ZFIRST: LDA ARG1+LO
JSR OBJLOC ; GET OBJECT ADDR INTO [I]
LDY #6 ; POINT TO "FIRST" SLOT
FIRST1: LDA (I),Y ; GET CONTENTS OF SLOT
JSR PUTBYT ; PASS IT TO VARIABLE
LDA VALUE+LO ; EXAMINE THE VALUE JUST "PUT"
BEQ PYUCK ; FAIL IF IT WAS ZERO
PFINE: JMP PREDS ; ELSE REJOICE
; ---
; LOC
; ---
; RETURN THE OBJECT CONTAINING OBJECT [ARG1];
; RETURN ZERO IF NONE
ZLOC: LDA ARG1+LO
JSR OBJLOC ; GET ADDR OF OBJECT INTO [I]
LDY #4 ; POINT TO "LOC" SLOT
LDA (I),Y ; GET THE BYTE
JMP PUTBYT ; AND SHIP IT OUT
; ------
; PTSIZE
; ------
; RETURN LENGTH OF PROP TABLE [ARG1] IN BYTES
ZPTSIZ: LDA ARG1+HI ; MOVE ABS ADDR OF
CLC ; THE PROP TABLE
ADC ZCODE ; INTO [I]
STA I+HI
LDA ARG1+LO ; DECREMENT THE
SEC ; ADDRESS
SBC #1 ; WHILE MOVING LSB
STA I+LO
BCS PTZ0
DEC I+HI
PTZ0: LDY #0 ; GET THE LENGTH
JSR PROPL ; OF PROPERTY AT [I] INTO [A]
CLC
ADC #1 ; INCREMENT RESULT
JMP PUTBYT ; AND RETURN IT
; ---
; INC
; ---
; INCREMENT VARIABLE [ARG1]
ZINC: LDA ARG1+LO
JSR VARGET ; FETCH VARIABLE INTO [VALUE]
JSR INCVAL ; INCREMENT IT
JMP ZD0
; ---
; DEC
; ---
; DECREMENT VARIABLE [ARG1]
ZDEC: LDA ARG1+LO
JSR VARGET ; FETCH VAR INTO [VALUE]
JSR DECVAL ; DECREMENT IT
ZD0: LDA ARG1+LO ; PUT RESULT BACK
JMP VARPUT ; INTO THE SAME VARIABLE
; ------
; PRINTB
; ------
; PRINT Z-STRING AT [ARG1]
ZPRB: LDA ARG1+LO
STA I+LO
LDA ARG1+HI
STA I+HI
JSR SETWRD ; MOVE Z-ADDR TO [MPC]
JMP PZSTR ; AND PRINT
; ------
; REMOVE
; ------
; MOVE OBJECT [ARG1] INTO PSEUDO-OBJECT #0
ZREMOV: LDA ARG1+LO ; GET SOURCE OBJECT ADDR
JSR OBJLOC ; INTO [I]
LDA I+LO ; COPY THE SOURCE ADDR
STA J+LO ; INTO [J]
LDA I+HI ; FOR LATER REFERENCE
STA J+HI
LDY #4 ; POINT TO "LOC" SLOT
LDA (I),Y ; GET THE DATA
BEQ REMVEX ; SCRAM IF NO OBJECT
JSR OBJLOC ; ELSE GET ADDR OF OBJECT [A] INTO [I]
LDY #6 ; POINT TO "FIRST" SLOT
LDA (I),Y ; GRAB DATA
CMP ARG1+LO ; IS THIS THE FIRST?
BNE REMVC1 ; NO, KEEP SEARCHING
LDY #5 ; ELSE COPY SOURCE'S "NEXT" SLOT
LDA (J),Y
INY ; INTO DEST'S "FIRST" SLOT ([Y] = 6)
STA (I),Y
BNE REMVC2 ; BRANCH ALWAYS
REMVC1: JSR OBJLOC
LDY #5 ; GET "NEXT"
LDA (I),Y
CMP ARG1+LO ; FOUND IT?
BNE REMVC1 ; NO, KEEP TRYING
LDY #5 ; WHEN FOUND
LDA (J),Y ; MOVE "NEXT" SLOT OF SOURCE
STA (I),Y ; TO "NEXT" SLOT OF DEST
REMVC2: LDA #0
LDY #4 ; CLEAR "LOC"
STA (J),Y
INY ; AND "NEXT" SLOTS ([Y] = 5)
STA (J),Y ; OF SOURCE OBJECT
REMVEX: RTS
; ------
; PRINTD
; ------
; PRINT SHORT DESCRIPTION OF OBJECT [ARG1]
ZPRD: LDA ARG1+LO
; ENTRY POINT FOR "USL"
PRNTDC: JSR OBJLOC ; GET ADDR OF OBJECT INTO [I]
LDY #7 ; GET PROP TABLE POINTER
LDA (I),Y ; FETCH MSB
TAX ; SAVE IT HERE
INY
LDA (I),Y ; FETCH LSB
STA I+LO ; STORE LSB
STX I+HI ; AND MSB
INC I+LO ; POINT PAST THE
BNE PDC0 ; LENGTH BYTE
INC I+HI
PDC0: JSR SETWRD ; CALC Z-STRING ADDR
JMP PZSTR ; AND PRINT IT
; ------
; RETURN
; ------
; RETURN FROM "CALL" WITH VALUE [ARG1]
ZRET: LDA OLDZSP ; RE-SYNC THE
STA ZSP ; Z-STACK POINTER
JSR POPVAL ; POP # LOCALS INTO [X/A]
STX I+HI ; SAVE HERE
TXA ; SET FLAGS; ANY LOCALS?
BEQ RET2 ; SKIP IF NOT
; RESTORE PUSHED LOCALS
DEX ; ZERO-ALIGN
TXA ; AND
ASL A ; WORD-ALIGN # LOCALS
STA I+LO ; FOR USE AS A STORAGE INDEX
RET1: JSR POPVAL ; POP A LOCAL INTO [X/A]
LDY I+LO ; RETRIEVE STORAGE INDEX
STA LOCALS+HI,Y ; STORE MSB OF LOCAL
TXA ; MOVE LSB
STA LOCALS+LO,Y ; AND STORE THAT TOO
DEC I+LO
DEC I+LO ; UPDATE STORAGE INDEX
DEC I+HI ; AND LOCALS COUNT
BNE RET1 ; POP TILL NO MORE LOCALS
; RESTORE OTHER VARIABLES
RET2: JSR POPVAL ; POP [ZPCH] AND [ZPCM]
STX ZPCM
STA ZPCH
JSR POPVAL ; POP AND RESTORE
STX OLDZSP
STA ZPCL
LDA #0
STA ZPCFLG ; ZPC CHANGED!
JSR A12VAL ; MOVE [ARG1] TO [VALUE]
JMP PUTVAL ; AND RETURN IT
; ----
; JUMP
; ----
; JUMP TO Z-LOCATION IN [ARG1]
ZJUMP: JSR A12VAL ; MOVE [ARG1] TO [VALUE]
JMP PREDB3 ; A BRANCH THAT ALWAYS SUCCEEDS
; -----
; PRINT
; -----
; PRINT Z-STRING AT WORD POINTER [ARG1]
ZPRINT: LDA ARG1+LO
STA I+LO
LDA ARG1+HI
STA I+HI
JSR SETSTR ; CALC STRING ADDRESS
JMP PZSTR ; AND PRINT IT
; -----
; VALUE
; -----
; RETURN VALUE OF VARIABLE [ARG1]
ZVALUE: LDA ARG1+LO
JSR VARGET ; GET THE VALUE
JMP PUTVAL ; EASY ENOUGH
; ----
; BCOM
; ----
; COMPLEMENT [ARG1]
ZBCOM: LDA ARG1+LO
EOR #$FF
TAX
LDA ARG1+HI
EOR #$FF
; FALL THROUGH ...
; ---------------------
; RETURN VALUE IN [X/A]
; ---------------------
VEXIT: STX VALUE+LO
STA VALUE+HI
JMP PUTVAL
END

442
atari/ops2.dip Normal file
View File

@@ -0,0 +1,442 @@
PAGE
SBTTL "--- 2-OPS ---"
; ---
; ADD
; ---
; RETURN [ARG1] + [ARG2]
GADD: LDA ARG1+LO
CLC
ADC ARG2+LO
TAX
LDA ARG1+HI
ADC ARG2+HI
JMP VEXIT
; ---
; SUB
; ---
; RETURN [ARG1] - [ARG2]
GSUB: LDA ARG1+LO
SEC
SBC ARG2+LO
TAX
LDA ARG1+HI
SBC ARG2+HI
JMP VEXIT
; ---
; MUL
; ---
; RETURN [ARG1] * [ARG2]
GMUL: JSR MINIT ; INIT LOOP AND TEMPS
GMLOOP: ROR MTEMP+HI
ROR MTEMP+LO
ROR ARG2+HI
ROR ARG2+LO
BCC GMNEXT
LDA ARG1+LO
CLC
ADC MTEMP+LO
STA MTEMP+LO
LDA ARG1+HI
ADC MTEMP+HI
STA MTEMP+HI
GMNEXT: DEX
BPL GMLOOP
LDX ARG2+LO ; [ARG2] CONTAINS PRODUCT
LDA ARG2+HI
JMP VEXIT
; ---
; DIV
; ---
; RETURN QUOTIENT OF [ARG1] / [ARG2]
GDIV: JSR DIVIDE
LDX QUOT+LO
LDA QUOT+HI
JMP VEXIT
; ---
; MOD
; ---
; RETURN REMAINDER OF [ARG1] / [ARG2]
GMOD: JSR DIVIDE
LDX REMAIN+LO
LDA REMAIN+HI
JMP VEXIT
; ---------------
; SIGNED DIVISION
; ---------------
; ENTRY: DIVIDEND IN [ARG1], DIVISOR IN [ARG2]
; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN]
DIVIDE: LDA ARG1+HI ; SIGN OF THE DIVIDEND
STA RSIGN ; IS SIGN OF REMAINDER
EOR ARG2+HI ; SIGN OF QUOTIENT IS POSITIVE
STA QSIGN ; IF SIGNS OF TERMS ARE THE SAME
LDA ARG1+LO ; MOVE [ARG1] TO [QUOT]
STA QUOT+LO
LDA ARG1+HI ; IS DIVIDEND POSITIVE?
STA QUOT+HI
BPL ABSDIV ; YES, CONTINUE
JSR ABQUOT ; ELSE CALC ABSOLUTE VALUE
ABSDIV: LDA ARG2+LO ; MOVE [ARG2] TO [REMAIN]
STA REMAIN+LO
LDA ARG2+HI ; IS DIVISOR POSITIVE?
STA REMAIN+HI
BPL GODIV ; IF NOT,
JSR ABREM ; CALC ABSOLUTE VALUE
GODIV: JSR UDIV ; UNSIGNED DIVIDE
LDA QSIGN ; SHOULD QUOTIENT BE FLIPPED?
BPL RFLIP ; NO, CHECK REMAINDER
JSR ABQUOT ; ELSE FLIP QUOTIENT
RFLIP: LDA RSIGN ; FLIP REMAINDER?
BPL DIVEX ; NO, SCRAM
; OR FALL THROUGH ...
; ----------------
; CALC ABS(REMAIN)
; ----------------
ABREM: LDA #0
SEC
SBC REMAIN+LO
STA REMAIN+LO
LDA #0
SBC REMAIN+HI
STA REMAIN+HI
DIVEX: RTS
; --------------
; CALC ABS(QUOT)
; --------------
ABQUOT: LDA #0
SEC
SBC QUOT+LO
STA QUOT+LO
LDA #0
SBC QUOT+HI
STA QUOT+HI
RTS
; -----------------
; UNSIGNED DIVISION
; -----------------
; ENTRY: DIVIDEND IN [QUOT], DIVISOR IN [REMAIN]
; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN]
UDIV: LDA REMAIN+LO
ORA REMAIN+HI
BEQ DIVERR ; CAN'T DIVIDE BY ZERO!
JSR MINIT ; INIT LOOP & TEMP REGISTER
UDLOOP: ROL QUOT+LO
ROL QUOT+HI
ROL MTEMP+LO
ROL MTEMP+HI
LDA MTEMP+LO
SEC
SBC REMAIN+LO
TAY
LDA MTEMP+HI
SBC REMAIN+HI
BCC UDNEXT
STY MTEMP+LO
STA MTEMP+HI
UDNEXT: DEX
BNE UDLOOP
ROL QUOT+LO ; SHIFT LAST CARRY
ROL QUOT+HI ; INTO QUOTIENT
LDA MTEMP+LO ; MOVE REMAINDER
STA REMAIN+LO ; INTO [REMAIN]
LDA MTEMP+HI
STA REMAIN+HI
RTS
; *** ERROR #8: DIVISION BY ZERO ***
DIVERR: LDA #8
JMP GERROR
; ---------
; MATH INIT
; ---------
MINIT: LDX #16 ; INIT BIT LOOP INDEX
LDA #0 ; CLEAR TEMP MATH REGISTER
STA MTEMP+LO
STA MTEMP+HI
CLC ; CLEAR FOR LOOPING
RTS
; ----
; BAND
; ----
; RETURN [ARG1] "AND" [ARG2]
GBAND: LDA ARG1+LO
AND ARG2+LO
TAX
LDA ARG1+HI
AND ARG2+HI
JMP VEXIT
; ----
; BIOR
; ----
; RETURN [ARG1] "OR" [ARG2]
GBIOR: LDA ARG1+LO
ORA ARG2+LO
TAX
LDA ARG1+HI
ORA ARG2+HI
JMP VEXIT
; ----
; BXOR
; ----
; RETURN [ARG1] "XOR" [ARG2]
GBXOR: LDA ARG1+LO
EOR ARG2+LO
TAX
LDA ARG1+HI
EOR ARG2+HI
JMP VEXIT
; -----
; BITS?
; -----
; IS EVERY "ON" BIT IN [ARG1] ALSO "ON" IN [ARG2]?
GBITSP: LDA ARG2+LO
AND ARG1+LO
CMP ARG2+LO
BNE PBAD
LDA ARG2+HI
AND ARG1+HI
CMP ARG2+HI
BNE PBAD
BEQ PGOOD
; ------
; EQUAL?
; ------
; DOES [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])?
GEQP: DEC NARGS ; ZERO-ALIGN ARGUMENT COUNT
LDX ARG1+LO ; FETCH LSB AND
LDA ARG1+HI ; MSB OF [ARG1]
CPX ARG2+LO ; LSB OF [ARG2] MATCHED?
BNE EQP1 ; NO, TRY NEXT ARG
CMP ARG2+HI ; MSBS MATCH?
BEQ PGOOD ; HOORAY!
EQP1: DEC NARGS ; OUT OF ARGS YET?
BEQ PBAD ; IF SO, SCRAM
CPX ARG3+LO ; ELSE CHECK [ARG3]
BNE EQP2
CMP ARG3+HI
BEQ PGOOD
EQP2: DEC NARGS ; ANOTHER ARG?
BEQ PBAD ; NO, EXIT
CPX ARG4+LO ; ELSE CHECK [ARG4]
BNE PBAD
CMP ARG4+HI
BNE PBAD
PGOOD: JMP PREDS
PBAD: JMP PREDF
; -----
; LESS?
; -----
; IS [ARG1] < [ARG2]?
GLESSP: JSR A12VAL ; MOVE [ARG1] INTO [VALUE]
JMP DLS0
; ------
; DLESS?
; ------
; DECREMENT [ARG1]; SUCCEED IF < [ARG2]
GDLESP: JSR GDEC
DLS0: LDA ARG2+LO ; MOVE [ARG2]
STA I+LO ; INTO [I]
LDA ARG2+HI
STA I+HI
JMP COMPAR ; [ARG1]-1 IS ALREADY IN [VALUE]
; -----
; GRTR?
; -----
; IS [ARG1] > [ARG2]?
GGRTRP: LDA ARG1+LO ; MOVE [ARG1]
STA I+LO ; INTO [I]
LDA ARG1+HI
STA I+HI
JMP A2VAL
; ------
; IGRTR?
; ------
; INCREMENT [ARG1]; SUCCEED IF > [ARG2]
GIGRTP: JSR GINC
LDA VALUE+LO ; MOVE [ARG1]-1
STA I+LO ; INTO [I]
LDA VALUE+HI
STA I+HI
A2VAL: LDA ARG2+LO ; MOVE [ARG2]
STA VALUE+LO ; INTO [VALUE]
LDA ARG2+HI
STA VALUE+HI
COMPAR: JSR SCOMP ; SIGNED COMPARE
BCC PGOOD
BCS PBAD
; -------------------------------
; SIGNED COMPARE OF [VALUE] & [I]
; -------------------------------
SCOMP: LDA I+HI
EOR VALUE+HI
BPL SCMP
LDA I+HI
CMP VALUE+HI
RTS
SCMP: LDA VALUE+HI
CMP I+HI
BNE SCEX
LDA VALUE+LO
CMP I+LO
SCEX: RTS
; ---
; SET
; ---
; SET VARIABLE [ARG1] EQUAL TO [ARG2]
GSET: LDA ARG2+LO ; MOVE [ARG2]
STA VALUE ; INTO [VALUE]
LDA ARG2+HI
STA VALUE+HI
LDA ARG1+LO ; GET VARIABLE ID
JMP VARPUT ; AND SET THE VALUE
; ---
; GET
; ---
; RETURN ITEM [ARG2] IN WORD-TABLE [ARG1]
GGET: JSR CALCW ; V-ADDR OF WORD IN [VPC]
;***
LDA #00
STA VPC0
;***
JSR GETBYT ; GET MSB OF VALUE
DOGET: STA VALUE+HI
JSR GETBYT ; AND LSB
STA VALUE+LO
JMP PUTVAL
; ----
; GETB
; ----
; RETURN ITEM [ARG2] IN BYTE-TABLE [ARG1]
GGETB: JSR CALCB ; V-ADDR OF BYTE IN [VPC]
LDA #0 ; MSB WILL BE ZERO
BEQ DOGET
; --------------------
; CALC TABLE ADDRESSES
; --------------------
;CALCW: ASL ARG2+LO ; WORD-ALIGN TABLE INDEX
; ROL ARG2+HI
;
;***
CALCB: LSR ARG2+HI ; BYTE-ALIGN TABLE INDEX
ROR ARG2+LO
LDA #00
ROL A ; PUT CARRY IN A
STA VPC0
;***
;CALCB: LDA ARG2+LO ; CALC LSB OF V-ADDRESS
;***
CALCW: LDA ARG2+LO ; CALC LSB OF V-ADDRESS
CLC
ADC ARG1+LO
STA VPCL
LDA ARG2+HI ; ALSO CALC MSB
ADC ARG1+HI
STA VPCH
LDA #0
STA VPCFLG ; INVALIDATE [VPC]
RTS
END

616
atari/ops2.src Normal file
View File

@@ -0,0 +1,616 @@
PAGE
SBTTL "--- 2-OPS ---"
; -----
; LESS?
; -----
; [ARG1] < [ARG2]?
ZLESS: JSR A12VAL ; MOVE [ARG1] TO [VALUE]
JMP DLS0 ; MOVE [ARG2] TO [I] & COMPARE
; ------
; DLESS?
; ------
; DECREMENT [ARG1]; SUCCEED IF < [ARG2]
ZDLESS: JSR ZDEC ; MOVES ([ARG1]-1) TO [VALUE]
DLS0: LDA ARG2+LO ; MOVE [ARG2] TO [I]
STA I+LO
LDA ARG2+HI
STA I+HI
JMP COMPAR ; COMPARE & RETURN
; -----
; GRTR?
; -----
; [ARG1] > [ARG2]?
ZGRTR: LDA ARG1+LO ; MOVE [ARG1] TO [I]
STA I+LO
LDA ARG1+HI
STA I+HI
JMP A2VAL ; MOVE [ARG2] TO [VALUE] & COMPARE
; ------
; IGRTR?
; ------
; INCREMENT [ARG1]; SUCCEED IF GREATER THAN [ARG2]
ZIGRTR: JSR ZINC ; GET ([ARG1]+1) INTO [VALUE]
LDA VALUE+LO ; MOVE [VALUE] TO [I]
STA I+LO
LDA VALUE+HI
STA I+HI
A2VAL: LDA ARG2+LO ; MOVE [ARG2] TO [VALUE]
STA VALUE+LO
LDA ARG2+HI
STA VALUE+HI
COMPAR: JSR SCOMP ; COMPARE [VALUE] AND [I]
BCC PGOOD
BCS PBAD
; -----------------
; SIGNED COMPARISON
; -----------------
; ENTRY: VALUES IN [VALUE] AND [I]
SCOMP: LDA I+HI
EOR VALUE+HI
BPL SCMP
LDA I+HI
CMP VALUE+HI
RTS
SCMP: LDA VALUE+HI
CMP I+HI
BNE SCEX
LDA VALUE+LO
CMP I+LO
SCEX: RTS
; ---
; IN?
; ---
; IS OBJECT [ARG1] CONTAINED IN OBJECT [ARG2]?
ZIN: LDA ARG1+LO
JSR OBJLOC ; GET ADDR OF TARGET OBJECT INTO [I]
LDY #4 ; POINT TO "LOC" SLOT
LDA (I),Y ; GET DATA
CMP ARG2+LO ; IS IT THERE?
BEQ PGOOD ; YES, SUCCEED
PBAD: JMP PREDF ; TOO BAD, CHUM ...
; ----
; BTST
; ----
; IS EVERY "ON" BIT IN [ARG1]
; ALSO "ON" IN [ARG2]?
ZBTST: LDA ARG2+LO ; FIRST CHECK LSBS
AND ARG1+LO
CMP ARG2+LO ; LSBS MATCH?
BNE PBAD ; NO, EXIT NOW
LDA ARG2+HI ; ELSE CHECK MSBS
AND ARG1+HI
CMP ARG2+HI ; MATCHED?
BNE PBAD ; SORRY ...
PGOOD: JMP PREDS
; ---
; BOR
; ---
; RETURN [ARG1] "OR" [ARG2]
ZBOR: LDA ARG1+LO
ORA ARG2+LO
TAX
LDA ARG1+HI
ORA ARG2+HI
JMP VEXIT
; ----
; BAND
; ----
; RETURN [ARG1] "AND" [ARG2]
ZBAND: LDA ARG1+LO
AND ARG2+LO
TAX
LDA ARG1+HI
AND ARG2+HI
JMP VEXIT
; -----
; FSET?
; -----
; IS FLAG [ARG1] SET IN OBJECT [ARG2]?
ZFSETP: JSR FLAGSU ; GET BITS INTO [K] AND [J]
LDA K+HI ; DO MSBS
AND J+HI
STA K+HI
LDA K+LO ; DO LSBS
AND J+LO
ORA K+HI ; ANY BITS ON?
BNE PGOOD ; TARGET BIT MUST BE ON
JMP PREDF
; ----
; FSET
; ----
; SET FLAG [ARG2] IN OBJECT [ARG1]
ZFSET: JSR FLAGSU ; GET BITS INTO [K] & [J], ADDR IN [I]
LDY #0
LDA K+HI ; FIRST DO MSBS
ORA J+HI
STA (I),Y
INY
LDA K+LO ; THEN LSBS
ORA J+LO
STA (I),Y
RTS
; ------
; FCLEAR
; ------
; CLEAR FLAG [ARG2] IN OBJECT [ARG1]
ZFCLR: JSR FLAGSU ; GETS BITS INTO [J] & [K], ADDR IN [I]
LDY #0
LDA J+HI ; FETCH MSB
EOR #$FF ; COMPLEMENT IT
AND K+HI ; RUB OUT FLAG
STA (I),Y
INY
LDA J+LO ; SAME FOR LSB
EOR #$FF
AND K+LO
STA (I),Y
RTS
; ---
; SET
; ---
; SET VARIABLE [ARG1] EQUAL TO [ARG2]
ZSET: LDA ARG2+LO ; MOVE THE VALUE
STA VALUE+LO ; INTO [VALUE]
LDA ARG2+HI
STA VALUE+HI
LDA ARG1+LO ; GET VARIABLE ID
JMP VARPUT ; AND CHANGE THE VARIABLE
; ----
; MOVE
; ----
; MOVE OBJECT [ARG1] INTO OBJECT [ARG2]
ZMOVE: JSR ZREMOV ; REMOVE FIRST
LDA ARG1+LO
JSR OBJLOC ; GET SOURCE OBJECT ADDR INTO [I]
LDA I+LO ; COPY SOURCE ADDRESS
STA J+LO ; INTO [J]
LDA I+HI
STA J+HI
LDA ARG2+LO ; GET DEST OBJECT ID
LDY #4 ; POINT TO "LOC" SLOT OF SOURCE
STA (I),Y ; AND MOVE IT IN
JSR OBJLOC ; GET ADDR OF DEST OBJECT INTO [I]
LDY #6 ; POINT TO "FIRST" SLOT
LDA (I),Y ; GET "FIRST" OF DEST
TAX ; SAVE HERE FOR A MOMENT
LDA ARG1+LO ; GET SOURCE OBJECT ID
STA (I),Y ; MAKE IT "FIRST" OF DEST
TXA ; RESTORE "FIRST" OF DEST
BEQ ZMVEX ; SCRAM IF ZERO
LDY #5 ; MAKE "FIRST" OF DEST
STA (J),Y ; THE "NEXT" OF SOURCE
ZMVEX: RTS
; ---
; GET
; ---
; RETURN ITEM [ARG2] IN WORD-TABLE [ARG1]
ZGET: JSR WCALC ; CALC ADDRESS
JSR GETBYT ; GET 1ST BYTE (MSB)
DOGET: STA VALUE+HI ; SAVE MSB
JSR GETBYT ; GET LSB
STA VALUE+LO ; SAVE AND
JMP PUTVAL ; HAND IT OVER
; ----
; GETB
; ----
; RETURN ITEM [ARG2] IN BYTE-TABLE AT [ARG1]
ZGETB: JSR BCALC
BEQ DOGET ; [A] = 0, SO CLEAR MSB OF [VALUE]
; --------------------
; CALC TABLE ADDRESSES
; --------------------
; WORD-ALIGNED ENTRY
WCALC: ASL ARG2+LO ; WORD-ALIGN FOR
ROL ARG2+HI ; WORD ACCESS
; BYTE-ALIGNED ENTRY
BCALC: LDA ARG2+LO ; ADD BASE ADDR OF TABLE
CLC ; TO ITEM
ADC ARG1+LO ; INDEX
STA MPCL
LDA ARG2+HI ; SAME FOR MSBS
ADC ARG1+HI
STA MPCM
LDA #0
STA MPCH ; CLEAR TOP BIT
STA MPCFLG ; & INVALIDATE [MPC]
RTS
; ----
; GETP
; ----
; RETURN PROPERTY [ARG2] OF OBJECT [ARG1];
; IF NO PROP [ARG2], RETURN [ARG2]'TH ELEMENT OF OBJECT #0
ZGETP: JSR PROPB
GETP1: JSR PROPN
CMP ARG2+LO
BEQ GETP3
BCC GETP2
JSR PROPNX
JMP GETP1 ; TRY AGAIN WITH NEXT PROP
GETP2: LDA ARG2+LO ; GET PROPERTY #
SEC ; ZERO-ALIGN IT
SBC #1
ASL A ; WORD-ALIGN IT
TAY ; USE AS AN INDEX
LDA (OBJTAB),Y ; GET MSB OF PROPERTY
STA VALUE+HI
INY
LDA (OBJTAB),Y ; DO SAME WITH LSB
STA VALUE+LO
JMP PUTVAL ; RETURN DEFAULT IN [VALUE]
GETP3: JSR PROPL
INY ; MAKE [Y] POINT TO 1ST BYTE OF PROP
TAX ; (SET FLAGS) IF LENGTH IN [A] = 0
BEQ GETPB ; GET A BYTE PROPERTY
CMP #1 ; IF LENGTH = 1
BEQ GETPW ; GET A WORD PROPERTY
; *** ERROR #7: PROPERTY LENGTH ***
LDA #7
JMP ZERROR
; GET A 1-BYTE PROPERTY
GETPB: LDA (I),Y ; GET LSB INTO [A]
LDX #0 ; CLEAR MSB IN [X]
BEQ ETPEX
; GET A 2-BYTE PROPERTY
GETPW: LDA (I),Y ; GET MSB
TAX ; INTO [X]
INY ; POINT TO LSB
LDA (I),Y ; GET IT INTO [A]
ETPEX: STA VALUE+LO ; STORE LSB
STX VALUE+HI ; AND MSB
JMP PUTVAL
; -----
; GETPT
; -----
; RETURN POINTER TO PROP TABLE [ARG2]
; IN OBJECT [ARG1]
ZGETPT: JSR PROPB
GETPT1: JSR PROPN ; RETURNS OFFSET IN [Y]
CMP ARG2+LO
BEQ GETPT2
BCC DORET
JSR PROPNX ; TRY NEXT PROPERTY
JMP GETPT1
GETPT2: INC I+LO
BNE GETPT3
INC I+HI
GETPT3: TYA ; FETCH OFFSET
CLC
ADC I+LO ; ADD LSB OF TABLE ADDRESS
STA VALUE+LO
LDA I+HI ; AND MSB
ADC #0
SEC ; STRIP OFF
SBC ZCODE ; RELATIVE POINTER
STA VALUE+HI
JMP PUTVAL ; AND RETURN
DORET: JMP RET0 ; ELSE RETURN A ZERO
; -----
; NEXTP
; -----
; RETURN INDEX # OF PROP FOLLOWING PROP [ARG2] IN OBJECT [ARG1];
; RETURN ZERO IF LAST; RETURN FIRST IF [ARG2]=0; ERROR IF NONE
ZNEXTP: JSR PROPB
LDA ARG2+LO ; IF [ARG2]=0
BEQ NXTP3 ; RETURN "FIRST" SLOT
NXTP1: JSR PROPN ; FETCH PROPERTY #
CMP ARG2+LO ; COMPARE TO TARGET #
BEQ NXTP2 ; FOUND IT!
BCC DORET ; LAST PROP, SO RETURN ZERO
JSR PROPNX ; ELSE TRY NEXT PROPERTY
JMP NXTP1
NXTP2: JSR PROPNX ; POINT TO FOLLOWING PROPERTY
NXTP3: JSR PROPN ; GET THE PROPERTY #
JMP PUTBYT ; AND RETURN IT
; ---
; ADD
; ---
; RETURN [ARG1] + [ARG2]
ZADD: LDA ARG1+LO ; ADD LSBS
CLC
ADC ARG2+LO
TAX ; SAVE LSB HERE
LDA ARG1+HI ; ADD MSBS
ADC ARG2+HI
JMP VEXIT
; ---
; SUB
; ---
; RETURN [ARG1] - [ARG2]
ZSUB: LDA ARG1+LO ; SUBTRACT LSBS
SEC
SBC ARG2+LO
TAX ; SAVE LSB HERE
LDA ARG1+HI ; SUBTRACT MSBS
SBC ARG2+HI
JMP VEXIT ; EXIT WITH [X]=LSB, [A]=MSB
; ---
; MUL
; ---
; RETURN [ARG1] * [ARG2]
ZMUL: JSR MINIT ; INIT THINGS
ZMLOOP: ROR MTEMP+HI
ROR MTEMP+LO
ROR ARG2+HI
ROR ARG2+LO
BCC ZMNEXT
LDA ARG1+LO
CLC
ADC MTEMP+LO
STA MTEMP+LO
LDA ARG1+HI
ADC MTEMP+HI
STA MTEMP+HI
ZMNEXT: DEX
BPL ZMLOOP
LDX ARG2+LO ; PUT LSB OF PRODUCT
LDA ARG2+HI ; AND MSB
JMP VEXIT ; WHERE "VEXIT" EXPECTS THEM
; ---
; DIV
; ---
; RETURN QUOTIENT OF [ARG1] / [ARG2]
ZDIV: JSR DIVIDE
LDX QUOT+LO
LDA QUOT+HI
JMP VEXIT
; ---
; MOD
; ---
; RETURN REMAINDER OF [ARG1] / [ARG2]
ZMOD: JSR DIVIDE
LDX REMAIN+LO ; FETCH THE REMAINDER
LDA REMAIN+HI ; IN [REMAIN]
JMP VEXIT ; AND RETURN IT
; ---------------
; SIGNED DIVISION
; ---------------
; ENTRY: DIVIDEND IN [ARG1], DIVISOR IN [ARG2]
; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN]
DIVIDE: LDA ARG1+HI ; SIGN OF REMAINDER
STA RSIGN ; IS THE SIGN OF THE DIVIDEND
EOR ARG2+HI ; SIGN OF QUOTIENT IS POSITIVE
STA QSIGN ; IF SIGNS OF TERMS ARE THE SAME
LDA ARG1+LO ; MOVE [ARG1] TO [QUOT]
STA QUOT+LO
LDA ARG1+HI
STA QUOT+HI ; IF DIVIDEND IS POSITIVE
BPL ABSDIV ; MOVE DIVISOR
JSR ABQUOT ; ELSE CALC ABS(DIVIDEND) FIRST
ABSDIV: LDA ARG2+LO
STA REMAIN+LO
LDA ARG2+HI
STA REMAIN+HI ; IF REMAINDER IS POSITIVE
BPL GODIV ; WE'RE READY TO DIVIDE
JSR ABREM ; ELSE CALC ABS(DIVISOR)
GODIV: JSR UDIV ; DO UNSIGNED DIVIDE
LDA QSIGN ; SHOULD QUOTIENT BE FLIPPED?
BPL RFLIP ; NO, TEST REMAINDER
JSR ABQUOT ; ELSE GET ABSOLUTE VALUE
RFLIP: LDA RSIGN ; SHOULD EMAINDER BE FLIPPED?
BPL DIVEX ; NO, WE'RE DONE
; ELSE FALL THROUGH ...
; ----------------
; CALC ABS(REMAIN)
; ----------------
ABREM: LDA #0
SEC
SBC REMAIN+LO
STA REMAIN+LO
LDA #0
SBC REMAIN+HI
STA REMAIN+HI
DIVEX: RTS
; --------------
; CALC ABS(QUOT)
; --------------
ABQUOT: LDA #0
SEC
SBC QUOT+LO
STA QUOT+LO
LDA #0
SBC QUOT+HI
STA QUOT+HI
RTS
; -----------------
; UNSIGNED DIVISION
; -----------------
; ENTRY: DIVIDEND IN [QUOT], DIVISOR IN [REMAIN]
; EXIT: QUOTIENT IN [QUOT], REMAINDER IN [REMAIN]
UDIV: LDA REMAIN+LO ; CHECK [REMAIN]
ORA REMAIN+HI ; BEFORE PROCEEDING
BEQ DIVERR ; CAN'T DIVIDE BY ZERO!
JSR MINIT ; SET IT ALL UP
UDLOOP: ROL QUOT+LO
ROL QUOT+HI
ROL MTEMP+LO
ROL MTEMP+HI
LDA MTEMP+LO
SEC
SBC REMAIN+LO
TAY ; SAVE HERE
LDA MTEMP+HI
SBC REMAIN+HI
BCC UDNEXT
STY MTEMP+LO
STA MTEMP+HI
UDNEXT: DEX
BNE UDLOOP
ROL QUOT+LO ; SHIFT LAST CARRY FOR QUOTIENT
ROL QUOT+HI
LDA MTEMP+LO ; MOVE REMAINDER
STA REMAIN+LO ; INTO [REMAIN]
LDA MTEMP+HI
STA REMAIN+HI
RTS
; *** ERROR #8: DIVISION BY ZERO ***
DIVERR: LDA #8
JMP ZERROR
; ---------
; MATH INIT
; ---------
MINIT: LDX #16 ; INIT LOOPING INDEX
LDA #0
STA MTEMP+LO ; CLEAR TEMP
STA MTEMP+HI ; REGISTER
CLC ; AND CARRY
RTS
END

387
atari/opsx.dip Normal file
View File

@@ -0,0 +1,387 @@
PAGE
SBTTL "--- X-OPS ---"
; ----
; CALL
; ----
; ENTRY: [NARGS] = 0
GCALL: LDX #15 ; FILL THE ARG-TYPE LIST
LDA #%11000000 ; WITH "NO MORE ARGS" BYTES
GCL: STA CTYPES,X
DEX
BPL GCL
LDA #4
STA ADEX ; INIT BYTE INDEX
STA ADEX2 ; AND ARG BYTE COUNTER
GCL0: JSR NEXTPC ; GRAB AN ARGUMENT BYTE
STA ABYTE ; SAVE IT HERE
JMP GCL2 ; SKIP OVER 1ST SHIFT
GCL1: LDA ABYTE
ASL A
ASL A
STA ABYTE
GCL2: AND #%11000000 ; MASK GARBAGE
CMP #%11000000 ; LAST ARGUMENT?
BEQ GCL3 ; YES, TIME TO DECODE ARGS
LDX NARGS ; ELSE ADD THIS ARGUMENT
STA CTYPES,X ; TO THE ARG-TYPE LIST
INC NARGS ; UPDATE # ARGUMENTS
DEC ADEX ; THIS ARG BYTE EMPTY?
BNE GCL1 ; NO, GET NEXT ARG
LDA #4 ; ELSE RESET
STA ADEX ; ARGUMENT INDEX
DEC ADEX2 ; DONE 4 ARG BYTES?
BNE GCL0 ; NO, GET ANOTHER
; [CTYPES] HAS LIST OF ARG TYPES
; [NARGS] HAS # ARGUMENTS
GCL3: LDA #0 ; RESET THE
STA ADEX ; ARGUMENT INDEX
STA ADEX2 ; AND STORAGE INDEX
LDA NARGS ; CONTINUE ONLY IF
BNE GCL4 ; [NARGS] <> 0
; *** ERROR #12: NO CALL ADDRESS ***
LDA #12
JMP GERROR
GCL4: LDX ADEX ; GET ARG INDEX
CPX NARGS ; OUT OF ARGS YET?
BEQ GCL8 ; YES IF [X] = [NARGS]
INC ADEX ; ELSE UPDATE THE INDEX
LDA CTYPES,X ; GET A TYPE BYTE
BNE GCL5
JSR GETLNG ; 00 = LONG IMMEDIATE
JMP GCL7
GCL5: CMP #%01000000
BNE GCL6
JSR GETSHT ; 01 = SHORT IMMEDIATE
JMP GCL7
GCL6: JSR GETVAR ; ELSE GET VARIABLE
; ARGUMENT IS NOW IN [VALUE]
GCL7: LDX ADEX2 ; GET STORAGE INDEX
LDA VALUE+LO ; MOVE LSB OF VALUE
STA CARGS,X ; INTO [CARGS]
LDA VALUE+HI ; ALSO MOVE
STA CARGS+1,X ; MSB
INX
INX ; UPDATE THE
STX ADEX2 ; STORAGE INDEX
BNE GCL4 ; LOOP BACK FOR ANOTHER ARGUMENT
; ARGUMENTS IN [CARGS], # ARGUMENTS IN [NARGS]
GCL8: LDA CARGS+LO ; IS CALL ADDRESS
ORA CARGS+HI ; ZERO?
BNE DOCALL ; NO, CONTINUE
JMP PUTBYT ; ELSE RETURN THE ZERO IN [A]
DOCALL: LDX OLDGSP ; SAVE [OLDGSP]
TXA
JSR PSHXA
LDX GPCL ; AND [GPC]
LDA GPCH
JSR PSHXA
;***
LDX GPC0
JSR PSHXA
;***
LDA CARGS+LO ; RESET [GPC]
STA GPCL
LDA CARGS+HI
STA GPCH
LDA #0
;***
STA GPC0 ; ALL FUNCTIONS START ON WORD BOUNDRIES
;***
STA GPCFLG ; AND ANNOUNCE CHANGE
JSR NEXTPC ; GET # LOCALS IN FUNCTION
STA ADEX ; SAVE HERE FOR REFERENCE
STA ADEX2 ; AND HERE FOR COUNTING
BEQ CALL2 ; IF ZERO, JUMP AHEAD
LDA #0
STA J+LO ; INIT LOOP INDEX
CALL1: LDY J+LO
LDX LOCALS,Y ; GET LSB OF LOCAL INTO [X]
LDA LOCALS+1,Y ; GET MSB INTO [A]
JSR PSHXA ; PUSH [X/A]
JSR NEXTPC ; GET MSB OF NEW LOCAL
LDY J+LO
STA LOCALS+1,Y ; MOVE MSB TO [LOCALS]
JSR NEXTPC ; GET LSB OF NEW LOCAL
LDY J+LO
STA LOCALS,Y ; STORE LSB
INY
INY
STY J+LO ; UPDATE STORAGE INDEX
DEC ADEX2 ; ANY MORE LOCALS?
BNE CALL1 ; YES, LOOP BACK
CALL2: DEC NARGS ; ANY ARGS LEFT?
BEQ CALL4 ; NO, SCRAM NOW
; PASS UP TO 15 [CARGS] TO [LOCALS]
LDX #0 ; INIT LOOP INDEX
CALL3: LDA CARGS+2,X ; GET LSB OF ARGUMENT
STA LOCALS,X ; ASSIGN TO A LOCAL
LDA CARGS+3,X ; SAME FOR
STA LOCALS+1,X ; MSB
INX ; POINT TO THE
INX ; NEXT ENTRIES
DEC NARGS ; OUT OF ARGS YET?
BNE CALL3 ; NO, KEEP LOOPING
; PUSH # LOCALS
CALL4: LDX ADEX ; # LOCALS KEPT HERE
TXA
JSR PSHXA
LDA GSP ; REMEMBER WHERE WE ARE
STA OLDGSP
JMP MLOOP ; BACK TO MAIN LOOP
; ---
; PUT
; ---
; SET ITEM [ARG2] IN WORD-TABLE [ARG1] EQUAL TO [ARG3]
;GPUT: ASL ARG2+LO ; WORD-ALIGN
; ROL ARG2+HI ; [ARG2]
; JSR PCALC
;***
GPUT: CLC
JSR PCALC ; GET ADDRESS INTO [I]
;***
LDA ARG3+HI
STA (I),Y ; [Y] = 0
INY
BNE PUTLSB ; BRANCH ALWAYS
; ----
; PUTB
; ----
; SET ITEM [ARG2] IN BYTE-TABLE [ARG1] EQUAL TO [ARG3]
;GPUTB: JSR PCALC
;***
GPUTB: CLC
LSR ARG2+HI ; DIVIDE BY TWO TO ADJUST FOR BYTE POINTING
ROR ARG2+LO ; LEAVE BIT 0 IN CARRY FOR PCALC
JSR PCALC
;***
PUTLSB: LDA ARG3+LO
STA (I),Y
RTS
; ------------------
; CALC "PUT" ADDRESS
; ------------------
PCALC: LDY #0 ; FOR INDEXING
;***
BCC PCALC1 ; TAKE CARE OF CARRY FROM GPUTB
INY
;***
PCALC1: LDA ARG2+LO ; ADD ITEM OFFSET
CLC ; TO TABLE ADDRESS
ADC ARG1+LO ; FIRST LSB
STA I+LO
LDA ARG2+HI ; THEN MSB
ADC ARG1+HI
ICENT: CMP GPURE ; IS CODE IN G-PRELOAD? (ENTRY FOR ICALC)
BCC USEGP ; YES, OK TO CHANGE
CMP ISTART ; IS IT BELOW THE I-FILE?
BCC PURERR ; CAN'T CHANGE PURE CODE!
CMP IPURE ; IS IT ABOVE THE I-PRELOAD?
BCS PURERR ; YES, UNCHANGEABLE!
; POINT TO BYTE IN I-PRELOAD
SEC
SBC ISTART ; STRIP OF V-OFFSET
;***
ASL I+LO ; *2
ROL A
****
CLC
ADC ICODE+HI ; MAKE IT ABSOLUTE
STA I+HI
;***
PCALC2: RTS
;***
; RTS
; POINT TO BYTE IN G-PRELOAD
;***
USEGP: ASL I+LO ; * 2 FOR 512 BYTE PAGES
ROL A
;***
CLC
ADC GCODE ; CALC ABSOLUTE ADDR
STA I+HI ; IN G-PRELOAD
RTS
; *** ERROR #9: PURITY VIOLATION ***
PURERR: LDA #9
JMP GERROR
; ------
; RANDOM
; ------
; RETURN A RANDOM VALUE BETWEEN 1 AND [ARG1]
GRAND: LDA ARG1+LO ; MAKE [ARG1]
STA ARG2+LO ; A DIVISOR
LDA ARG1+HI
STA ARG2+HI
JSR DORAND ; GET RANDOM BYTES
STX ARG1+LO ; INTO [A] & [X]
AND #%01111111 ; MAKE IT A POSITIVE
STA ARG1+HI ; DIVIDEND
JSR DIVIDE ; SIGNED DIVISION
LDA REMAIN+LO ; GRAB THE REMAINDER
STA VALUE+LO
LDA REMAIN+HI
STA VALUE+HI
JSR INCVAL ; INCREMENT IT
JMP PUTVAL ; AND RETURN THE RESULT
;-------------------------------------
; GITER: INITIALIZE ITERATION TABLE AT
; WORD-ADDRESS ARG1
;-------------------------------------
GITER: LDA #00 ; SET ARG4=0 FOR ICALC
STA ARG4+LO
STA ARG4+HI
LDA ARG1+HI ; MOVE ARG1 TO ARG3
STA ARG3+HI
LDA ARG1+LO
STA ARG3+LO
JSR ICALC ; THIS WILL ALSO CHECK PURITY VIOLATIONS
LDA (I),Y ; GET NUMBER OF ENTRIES IN TABLE
STA ITICN
INY
TYA ; INIT ICOUNT Y=1 A=1
STA (I),Y
INC ARG4+LO ; POINT TO FIRST WORD OF FIRST ENTRY
GITER1: JSR ICALC
LDA (I),Y ; HIGH BYTE OF ICON ADDRESS
PHA ; SAVE
INY ; =1
LDA (I),Y ; LOWBYTE OF ADDRESS
TAX
PLA
JSR GETI ; GET ICON INFORMATION
LDA #0
LDY #6
STA (I),Y ; SET NEGATE FOR POSITIVE DISPLAY
INY ; =7
LDA #1
STA (I),Y ; SET FIRST ITERATION=1
INY ; =8
LDA BSET
STA (I),Y ; SAVE BSET
INY ; =9
LDA ITERS
STA (I),Y ; SAVE # OF ITERS
INY ; =10
LDA IX1
STA (I),Y ; SAVE ICON WIDTH
INY ; =11
LDA IY1
STA (I),Y ; SAVE ICON HEIGHTH
JSR NXTENT
DEC ITICN
BNE GITER1
RTS
;------------------------
; GDUMP : NOT IMPLIMENTED
; RETURN 0
;------------------------
GDUMP: JMP RET0
;-------------------------
; GLOAD : NOT IMPLIMENTED
; RETURN 0
;------------------------
GLOAD: JMP RET0
END

348
atari/opsx.src Normal file
View File

@@ -0,0 +1,348 @@
PAGE
SBTTL "--- X-OPS ---"
; ------
; EQUAL?
; ------
; IS [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])?
ZEQUAL: DEC NARGS ; DOUBLE-CHECK # ARGS
BNE DOEQ ; MUST BE AT LEAST TWO, OR ...
; *** ERROR #9: NOT ENOUGH "EQUAL?" ARGS ***
LDA #9
JMP ZERROR
DOEQ: LDA ARG1+LO ; FETCH LSB
LDX ARG1+HI ; AND MSB OF [ARG1]
CMP ARG2+LO ; TEST LSB OF [ARG2]
BNE TRY2 ; NO GOOD, LOOK FOR ANOTHER ARG
CPX ARG2+HI ; ELSE TRY MSB OF [ARG2]
BEQ EQOK ; MATCHED!
TRY2: DEC NARGS ; OUT OF ARGS YET?
BEQ EQBAD ; YES, WE FAILED
CMP ARG3+LO ; TRY LSB OF [ARG3]
BNE TRY3 ; NO GOOD, LOOK FOR ANOTHER ARG
CPX ARG3+HI ; HOW ABOUT MSB OF [ARG3]?
BEQ EQOK ; YAY!
TRY3: DEC NARGS ; OUT OF ARGS YET?
BEQ EQBAD ; IF NOT ...
CMP ARG4+LO ; TRY [ARG4]
BNE EQBAD ; SORRY, CHUM
CPX ARG4+HI ; MSB MATCHED?
BNE EQBAD ; TOO BAD
EQOK: JMP PREDS ; FINALLY MATCHED!
EQBAD: JMP PREDF ; FAILURE (SNIFF!)
; ----
; CALL
; ----
; BRANCH TO FUNCTION AT ([ARG1]*2), PASSING
; OPTIONAL PARAMETERS IN [ARG2]-[ARG4]
ZCALL: LDA ARG1+LO
ORA ARG1+HI ; IS CALL ADDRESS ZERO?
BNE DOCALL ; NO, CONTINUE
JMP PUTBYT ; ELSE RETURN THE ZERO IN [A]
DOCALL: LDX OLDZSP ; SAVE OLD STACK POINTER
LDA ZPCL ; AND LSB OF [ZPC]
JSR PUSHXA ; ON THE Z-STACK
LDX ZPCM ; SAVE MIDDLE 8 BITS
LDA ZPCH ; AND TOP BIT OF [ZPC]
JSR PUSHXA ; AS WELL
; FORM 16-BIT ADDRESS FROM [ARG1]
LDA #0 ; CLEAR HIGH BIT FOR ROTATE
STA ZPCFLG ; AND INVALIDATE [ZPC]
ASL ARG1+LO ; MULTIPLY [ARG1]
ROL ARG1+HI ; BY TWO
ROL A ; HIGH BIT INTO [A]
STA ZPCH ; NEW HIGH BIT OF [ZPC]
LDA ARG1+HI ; GET NEW LOW BYTES
STA ZPCM
LDA ARG1+LO
STA ZPCL
JSR NEXTPC ; FETCH # LOCALS TO PASS
STA J+LO ; SAVE HERE FOR COUNTING
STA J+HI ; AND HERE FOR LATER REFERENCE
BEQ ZCALL2 ; SKIP IF NO LOCALS
LDA #0
STA I+LO ; ELSE INIT STORAGE INDEX
ZCALL1: LDY I+LO
LDX LOCALS+LO,Y ; GET LSB OF LOCAL INTO [X]
LDA LOCALS+HI,Y ; AND MSB INTO [A]
STY I+LO ; SAVE THE INDEX
JSR PUSHXA ; PUSH LOCAL IN [X/A] ONTO Z-STACK
JSR NEXTPC ; GET MSB OF NEW LOCAL
STA I+HI ; SAVE IT HERE
JSR NEXTPC ; NOW GET LSB
LDY I+LO ; RESTORE INDEX
STA LOCALS+LO,Y ; STORE LSB INTO [LOCALS]
LDA I+HI ; RETRIEVE MSB
STA LOCALS+HI,Y ; STORE IT INTO [LOCALS]
INY
INY ; UPDATE
STY I+LO ; THE STORAGE INDEX
DEC J+LO ; ANY MORE LOCALS?
BNE ZCALL1 ; YES, KEEP LOOPING
; MOVE UP TO 3 ARGUMENTS TO [LOCALS]
ZCALL2: DEC NARGS ; EXTRA ARGS IN THIS CALL?
BEQ ZCALL3 ; NO, CONTINUE
LDA ARG2+LO ; MOVE [ARG2] TO LOCAL #1
STA LOCALS+LO
LDA ARG2+HI
STA LOCALS+HI
DEC NARGS ; ANY LEFT?
BEQ ZCALL3 ; NO, SCRAM
LDA ARG3+LO ; MOVE [ARG3] TO LOCAL #2
STA LOCALS+LO+2
LDA ARG3+HI
STA LOCALS+HI+2
DEC NARGS ; ANY LEFT?
BEQ ZCALL3 ; NO, EXUENT
LDA ARG4+LO ; MOVE [ARG4] TO LOCAL #3
STA LOCALS+LO+4
LDA ARG4+HI
STA LOCALS+HI+4
ZCALL3: LDX J+HI ; RETRIEVE # LOCALS
TXA ; DUPE FOR NO GOOD REASON
JSR PUSHXA ; PUSH # LOCALS ONTO Z-STACK
LDA ZSP ; REMEMBER WHERE
STA OLDZSP ; WE CAME FROM
RTS ; WHEW!
; ---
; PUT
; ---
; SET ITEM [ARG2] IN WORD-TABLE [ARG1] EQUAL TO [ARG3]
ZPUT: ASL ARG2+LO ; WORD-ALIGN [ARG2]
ROL ARG2+HI
JSR PCALC ; GET ITEM ADDR INTO [I]
LDA ARG3+HI ; STORE MSB OF [ARG3]
STA (I),Y ; INTO MSB OF TABLE POSITION
INY ; POINT TO LSB
BNE PUTLSB ; BRANCH ALWAYS
; ----
; PUTB
; ----
; SET ITEM [ARG2] IN BYTE-TABLE [ARG1] EQUAL TO [ARG3]
ZPUTB: JSR PCALC
; ENTRY FOR "PUT"
PUTLSB: LDA ARG3+LO ; GET LSB OF [ARG3]
STA (I),Y ; STORE IN TABLE AT [Y]
RTS
; ---------------------------
; CALC ITEM ADDRESS FOR "PUT"
; ---------------------------
PCALC: LDA ARG2+LO ; ADD ITEM OFFSET IN [ARG2]
CLC ; TO TABLE ADDR IN [ARG1]
ADC ARG1+LO ; TO FORM A POINTER
STA I+LO ; IN [I]
LDA ARG2+HI ; SAME FOR MSB
ADC ARG1+HI
CLC
ADC ZCODE ; MAKE IT ABSOLUTE
STA I+HI
LDY #0 ; ZERO FOR INDEXING
RTS
; ----
; PUTP
; ----
; SET PROPERTY [ARG2] IN OBJECT [ARG1] EQUAL TO [ARG3]
ZPUTP: JSR PROPB
PUTP1: JSR PROPN
CMP ARG2+LO
BEQ PUTP2
BCC PNERR ; ERROR IF LOWER
JSR PROPNX ; TRY NEXT PROPERTY
JMP PUTP1
PUTP2: JSR PROPL
INY ; MAKE [Y] POINT TO 1ST PROPERTY BYTE
TAX ; (SET FLAGS) IF LENGTH IN [A] = 0
BEQ PUTP3 ; PUT A BYTE
CMP #1 ; PUT A WORD IF [A] = 1
BNE PLERR ; ELSE LENGTH IS BAD
LDA ARG3+HI ; GET MSB OF PROPERTY
STA (I),Y ; AND STORE IN OBJECT
INY ; POINT TO LSB SLOT
PUTP3: LDA ARG3+LO ; FETCH LSB
STA (I),Y ; AND STORE IN OBJECT
RTS
; *** ERROR #10: BAD PROPERTY NUMBER ***
PNERR: LDA #10
JMP ZERROR
; *** ERROR #11: PUTP PROPERTY LENGTH ***
PLERR: LDA #11
JMP ZERROR
; ------
; PRINTC
; ------
; PRINT CHAR WITH ASCII VALUE IN [ARG1]
ZPRC: LDA ARG1+LO ; GRAB THE CHAR
JMP COUT ; AND SHIP IT OUT
; ------
; PRINTN
; ------
; PRINT VALUE OF [ARG1] AS A SIGNED INTEGER
ZPRN: LDA ARG1+LO ; MOVE [ARG1] TO [QUOT]
STA QUOT+LO
LDA ARG1+HI
STA QUOT+HI
; PRINT [QUOT]
NUMBER: LDA QUOT+HI ; IF VALUE IS POSITIVE
BPL DIGCNT ; CONTINUE
LDA #$2D ; ELSE START WITH A MINUS SIGN
JSR COUT
JSR ABQUOT ; AND CALC ABS([QUOT])
; COUNT # OF DECIMAL DIGITS
DIGCNT: LDA #0 ; RESET
STA DIGITS ; DIGIT INDEX
DGC: LDA QUOT+LO ; IS QUOTIENT
ORA QUOT+HI ; ZERO YET?
BEQ PRNTN3 ; YES, READY TO PRINT
LDA #10 ; ELSE DIVIDE [QUOT]
STA REMAIN+LO ; BY 10 (LSB)
LDA #0
STA REMAIN+HI ; 10 (MSB)
JSR UDIV ; UNSIGNED DIVIDE
LDA REMAIN+LO ; FETCH LSB OF REMAINDER (THE DIGIT)
PHA ; SAVE IT ON STACK
INC DIGITS ; UPDATE DIGIT COUNT
BNE DGC ; LOOP TILL QUOTIENT=0
PRNTN3: LDA DIGITS ; IF DIGIT COUNT IS NZ
BNE PRNTN4 ; CONTINUE
LDA #'0' ; ELSE PRINT "0"
JMP COUT ; AND RETURN
PRNTN4: PLA ; PULL A DIGIT OFF THE STACK
CLC
ADC #'0' ; CONVERT TO ASCII
JSR COUT ; AND PRINT IT
DEC DIGITS ; OUT OF DIGITS YET?
BNE PRNTN4 ; NO, KEEP LOOPING
RTS
; ------
; RANDOM
; ------
; RETURN A RANDOM VALUE BETWEEN 0 AND [ARG1]
ZRAND: LDA ARG1+LO ; MAKE [ARG1] THE DIVISOR
STA ARG2+LO
LDA ARG1+HI
STA ARG2+HI
JSR RANDOM ; GET RANDOM BYTES INTO [A] AND [X]
STX ARG1+LO ; MAKE THEM THE DIVIDEND
AND #$7F ; MAKE SURE MSB IS POSITIVE
STA ARG1+HI
JSR DIVIDE ; SIGNED DIVIDE, [ARG1] / [ARG2]
LDA REMAIN+LO ; MOVE REMAINDER
STA VALUE+LO ; INTO [VALUE]
LDA REMAIN+HI
STA VALUE+HI
JSR INCVAL ; INCREMENT [VALUE]
JMP PUTVAL ; AND RETURN RESULT
; ----
; PUSH
; ----
; PUSH [ARG1] ONTO THE Z-STACK
ZPUSH: LDX ARG1+LO
LDA ARG1+HI
JMP PUSHXA
; ---
; POP
; ---
; POP WORD OFF Z-STACK, STORE IN VARIABLE [ARG1]
ZPOP: JSR POPVAL ; VALUE INTO [VALUE]
LDA ARG1+LO ; GET VARIABLE ID
JMP VARPUT ; AND CHANGE THE VARIABLE
END

313
atari/paging.dip Normal file
View File

@@ -0,0 +1,313 @@
PAGE
SBTTL "--- PAGING ROUTINES ---"
; -----------------------
; GET NEXT BYTE OF G-CODE
; -----------------------
; EXIT: BYTE IN [A] & [Y], FLAGS SET
NEXTPC: LDA GPCFLG ; IS [GPOINT] VALID?
BNE NPC2 ; YES, CONTINUE
LDX GPCH ; GET TARGET V-PAGE
LDA MEMMAP,X ; IS IT ALREADY RESIDENT?
BEQ NPC0 ; NO, PAGE IT IN
CMP PAGE0 ; IS IT IN PRELOAD?
BCC NPC1 ; YES, CONTINUE
; HANDLE A RESIDENT "PURE" PAGE
JSR UPTIME ; UPDATE STAMP
JMP NPC1 ; CONTINUE W/PAGE ADDR IN [A]
; FETCH A NON-RESIDENT "PURE" PAGE
NPC0: STA VPCFLG ; ([A]=0) INVALIDATE [VPC]
JSR PAGE ; GET ABS PAGE OF V-BLOCK [X] IN [A]
JMP NEXTPC
;THIS JUMP SHOULD NOT BE NEEDED BUT SEEMS TO HELP
; [A] HAS ABS ADDR OF TARGET PAGE (FIRST RAM PAGE OF TWO PAGES)
NPC1: STA GPOINT+HI ; FORM MSB OF G-POINTER
LDA GPCL ; IF BIT 7 SET
BPL NPC1A
INC GPOINT+HI ; POINT [GPOINT] AT NEXT RAM PAGE
NPC1A: LDA #$FF
STA GPCFLG ; VALIDATE [GPC]
; [GPOINT] HAS POINTER TO ABS PAGE ADDR
; PUT BITS 0 THRU 7 OF GPC INTO <Y>
NPC2: LDA GPC0 ; PUT BIT 0 INTO <C>
LSR A
LDA GPCL ; GET BITS 1-8
ROL A ; DON'T WORRY ABOUT BIT 8
TAY
LDA (GPOINT),Y ; GET A G-BYTE
; INCREMENT [GPC]
; IF CROSSING A !RAM! PAGE ADJUST [GPOINT]
; IF CROSSING A V-PAGE INVALIDATE FLAG
PHA ; SAVE THE BYTE
LDA GPC0 ; EFFECTIVLY ADD 1
EOR #$01
STA GPC0
BNE NPC3 ; BRANCH NO CARRY
INC GPCL
BEQ NPC4 ; BRANCH CROSSED V-PAGE
LDA GPCL ; TEST FOR CROSS !RAM! PAGE
AND #$7F
BNE NPC3 ; BRANCH NO CROSS
INC GPOINT+HI ; ADJUST RAM POINTER
JMP NPC3
NPC4: INC GPCH ; CROSS V-PAGE
LDA #00
STA GPCFLG ; INVALIDATE FLAG
NPC3: PLA ; RESTORE BYTE
TAY ; SET FLAGS
RTS
; ----------------------------
; GET A BYTE OF VIRTUAL MEMORY
; ----------------------------
; EXIT: SAME AS "NEXTPC"
GETBYT: LDA VPCFLG ; [VPC] VALID?
BNE GTBT2 ; YES, CONTINUE
LDX VPCH ; GET TARGET V-PAGE
LDA MEMMAP,X ; ALREADY IN RAM?
BEQ GTBT0 ; NO, PAGE IT IN
CMP PAGE0 ; IS IT PRELOADED?
BCC GTBT1 ; YES, CONTINUE
; HANDLE A RESIDENT PAGE
JSR UPTIME ; STAMP PAGE & UPDATE STAMP
JMP GTBT1 ; CONTINUE W/BUFFER ADDR IN [A]
; HANDLE A NON-RESIDENT PAGE
GTBT0: STA GPCFLG ; ([A]=0) INVALIDATE [GPC]
JSR PAGE ; GET ABS PAGE OF V-BLOCK [X] INTO [A]
JMP GETBYT
;THIS JMP SHOULD NOT BE NEEDED BUT SEEMS TO HELP
; [A] HAS ABS PAGE # OF TARGET PAGE
GTBT1: STA VPOINT+HI ; SET MSB OF POINTER
LDA VPCL ; IF BIT 7 SET
BPL GTBT1A
INC VPOINT+HI ; POINT AT NEXT RAM PAGE
GTBT1A: LDA #$FF
STA VPCFLG ; VALIDATE [VPC]
; [VPOINT] POINTS TO ABS ADDR OF TARGET V-PAGE
; PUT BITS 0 THRU 7 OF GPC INTO <Y>
GTBT2: LDA VPC0 ; PUT BIT 0 INTO <C>
LSR A
LDA VPCL ; GET BITS 1-8
ROL A ; DON'T WORRY ABOUT BIT 8
TAY
LDA (VPOINT),Y ; GET A V-BYTE
; INCREMENT [VPC]
; IF CROSSING A !RAM! PAGE ADJUST [GPOINT]
; IF CROSSING A V-PAGE INVALIDATE FLAG
PHA ; SAVE THE BYTE
LDA VPC0 ; EFFECTIVLY ADD 1
EOR #$01
STA VPC0
BNE GTBT3 ; BRANCH NO CARRY
INC VPCL
BEQ GTBT4 ; BRANCH CROSSED V-PAGE
LDA VPCL ; TEST FOR CROSS !RAM! PAGE
AND #$7F
BNE GTBT3 ; BRANCH NO CROSS
INC VPOINT+HI ; ADJUST RAM POINTER
JMP GTBT3
GTBT4: INC VPCH ; CROSS V-PAGE
LDA #00
STA VPCFLG ; INVALIDATE FLAG
GTBT3: PLA ; RESTORE BYTE
TAY ; SET FLAGS
RTS
; -------------------------------
; LOCATE A PAGE OF VIRTUAL MEMORY
; -------------------------------
;-----------------------------------------------------------------
; A VIRTUAL PAGE IS 512 BYTES OF VIRTUAL MEMORY.
; WHEN PAGED INTO MACHINE RAM IT MUST OCCUPY TWO CONSECUTIVE
; 256 BYTE !RAM! PAGES.
;
; [PAGMAP],BUFFER RETURN THE V-PAGE IN THAT BUFFFER
; (A BUFFER IS TWO CONSECUTIVE RAM PAGES)
; [MEMMAP],VPAGE RETURNS RAM PAGE LOWER HALF OF VPAGE IS IN
;
; [PAGE0] - RAM PAGE WHERE BUFFER(0) STARTS
;-----------------------------------------------------------------
; ENTRY: V-BLOCK TO SEARCH FOR IN [X]
; EXIT: ABSOLUTE PAGE ADDRESS IN [A]
PAGE: STX DBLOCK ; GIVE TARGET V-PAGE TO GROS
; DE-ALLOCATE THE EARLIEST V-PAGE
PGE1: JSR EARLY ; GET INDEX OF EARLIEST BUFFER INTO [SWAP]
LDY SWAP
LDX PAGMAP,Y ; GET V-PAGE OF EARLIEST BUFFER
BEQ PGE2 ; 0 = NO PAGE IN BUFFER
LDA #0
STA MEMMAP,X ; ZERO THE [MEMMAP] ENTRY
; SPLICE THE TARGET PAGE INTO THE BUFFER MAP
PGE2: LDA DBLOCK ; TARGET V-PAGE
STA PAGMAP,Y ; ADD IT TO BUFFER MAP
TAX ; USE LATER FOR INDEX INTO [MEMMAP]
TYA ; CALC THE ABSOLUTE ADDRESS
ASL A ; * 2 FOR 512 BYTE VPAGES
CLC ; OF THE
ADC PAGE0 ; CORRESPONDING BUFFER
STA MEMMAP,X ; TELL [MEMMAP] WHERE TO FIND THE PAGE
STA DBUFF+HI ; TELL GROS WHERE THE BUFFER IS
STA TARGET ; SAVE HERE
JSR GETDSK ; GET PAGE [DBLOCK] INTO [DBUFF]
LDA TARGET ; RESTORE BUFFER PAGE
; FALL THROUGH ...
; ----------------
; UPDATE TIMESTAMP
; ----------------
; ENTRY: ABS BUFFER PAGE OF V-BLOCK
UPTIME: STA TARGET ; SAVE FOR LATER
SEC ; FORM A ZERO-ALIGNED
SBC PAGE0 ; INDEX
;***
LSR A ; / 2 FOR 512 BYTE PAGES
;***
TAY ; INTO [LRUMAP]
LDA LRUMAP,Y ; CHECK THIS PAGE'S STAMP
CMP STAMP ; SAME AS CURRENT STAMP?
BEQ UT3 ; EXIT NOW IF SO
INC STAMP ; ELSE UPDATE STAMP
BNE UT2 ; CONTINUE IF NO OVERFLOW
; HANDLE STAMP OVERFLOW
JSR EARLY2 ; GET EARLIEST STAMP INTO [LRU]
LDX #0 ; INIT INDEX
UT0: LDA LRUMAP,X ; ELSE GET A STAMP READING
BEQ UT1 ; EXIT IF ZERO
SEC ; SUBTRACT OFF
SBC LRU ; EARLIEST STAMP READING
STA LRUMAP,X ; REPLACE IN MAP
UT1: INX
CPX PMAX ; LOOP TILL
BCC UT0 ; ALL STAMPS FIXED
LDA #0 ; TURN BACK
SEC ; THE CLOCK
SBC LRU ; TO REFLECT STAMP FUDGING
STA STAMP
UT2: LDA STAMP ; STAMP BUFFER [Y]
STA LRUMAP,Y ; WITH THE NEW STAMP
UT3: LDA TARGET ; RESTORE BUFFER ADDR
RTS
; --------------------------------
; LOCATE EARLIEST ACTIVE TIMESTAMP
; --------------------------------
; EXIT: [LRU] = EARLIEST TIMESTAMP
; [SWAP] = INDEX TO EARLIEST BUFFER
EARLY: LDX #0 ; INIT INDEX
STX SWAP
LDA LRUMAP ; GET TIMESTAMP OF BUFFER #0
INX ; START COMPARE WITH BUFFER #1
EAR0: CMP LRUMAP,X ; IS THIS STAMP EARLIER THAN [A]?
BCC EAR1 ; IF STILL SMALLER, TRY NEXT STAMP
LDA LRUMAP,X ; ELSE CHANGE EARLIEST ENTRY
STX SWAP ; AND UPDATE BUFFER INDEX
EAR1: INX
CPX PMAX ; OUT OF BUFFERS?
BCC EAR0 ; LOOP TILL EMPTY
RTS ; [SWAP] HAS INDEX TO EARLIEST BUFFER
; THIS IS FOR OVERFLOW, IGNORES 0 ENTRIES
SAVEY: DB 0
EARLY2: LDX #0 ; INIT INDEX
STX SWAP
STY SAVEY
EAR23: LDA LRUMAP,X ; GET TIMESTAMP OF BUFFER #0
CMP #0 ; DON'T USE A ZERO VALUE
BNE EAR22 ; OK, NOT 0
INX
CPX PMAX ; OUT OF BUFFERS?
BCC EAR23 ; NO, KEEP LOOKING
BCS EAR24 ; YUP, SO WILL HAVE TO USE 0
EAR22: INX ; START COMPARE WITH NEXT BUFFER
EAR20: CMP LRUMAP,X ; IS THIS STAMP EARLIER THAN [A]?
BCC EAR21 ; IF STILL SMALLER, TRY NEXT STAMP
LDY LRUMAP,X
BEQ EAR21
TYA
STX SWAP
EAR21: INX
CPX PMAX ; OUT OF BUFFERS?
BCC EAR20 ; LOOP TILL EMPTY
EAR24: STA LRU ; [A] HAS EARLIEST STAMP
; CMP #2 ; DON'T MAKE IT 0
; BCC EAR25
DEC LRU ; MAKE SO END RESULT NOT 0
EAR25: LDY SAVEY
RTS ; [SWAP] HAS INDEX TO EARLIEST BUFFER
END

239
atari/paging.src Normal file
View File

@@ -0,0 +1,239 @@
PAGE
SBTTL "--- TIME-STAMP PAGING ROUTINE ---"
; -------------------------
; FETCH NEXT BYTE OF Z-CODE
; -------------------------
; EXIT: BYTE AT [ZPC] IN [A] & [Y]; FLAGS SET
NEXTPC: LDA ZPCFLG ; IS [ZPCPNT] VALID?
BNE NPC2 ; YES, GET THE BYTE
; Z-PAGE HAS CHANGED!
LDA ZPCM ; GET TOP
LDY ZPCH ; 9 BITS OF [ZPC]
BNE NPC0 ; SWAP PAGE IF TOP BIT IS SET
CMP ZPURE ; IS THIS PAGE PRELOADED?
BCS NPC0 ; NO, SWAP IT IN
ADC ZCODE ; ELSE MAKE IT ABSOLUTE
BNE NPC1 ; AND GIVE IT TO [ZPCPNT]
NPC0: LDX #0
STX MPCFLG ; INVALIDATE [MPC]
JSR PAGE ; AND GET ABS PAGE ADDR INTO [A]
NPC1: STA ZPCPNT+HI ; SET ABS PAGE ADDRESS
LDX #$FF
STX ZPCFLG ; VALIDATE [ZPCPNT]
INX ; = 0
STX ZPCPNT+LO ; CLEAR LSB OF POINTER
NPC2: LDY ZPCL ; FETCH PAGE INDEX
LDA (ZPCPNT),Y ; GET Z-BYTE
INC ZPCL ; END OF PAGE YET?
BNE NPC3 ; NO, EXIT
LDY #0
STY ZPCFLG ; ELSE INVALIDATE [ZPCPNT]
INC ZPCM ; POINT [ZPC] TO
BNE NPC3 ; THE NEXT
INC ZPCH ; Z-PAGE
NPC3: TAY ; SET FLAGS
RTS ; AND RETURN
; -------------------------------
; GET NEXT BYTE OF VIRTUAL MEMORY
; -------------------------------
; EXIT: BYTE AT [MPC] IN [A] & [Y]; FLAGS SET
GETBYT: LDA MPCFLG ; IS [MPCPNT] VALID?
BNE GTBT2 ; YES, GET THE BYTE
; Z-PAGE HAS CHANGED!
LDA MPCM ; GET TOP
LDY MPCH ; 9 BITS OF [MPC]
BNE GTBT0 ; SWAP PAGE IF TOP BIT IS SET
PATCH EQU $+1 ; PATCH POINT FOR "VERIFY"
CMP ZPURE ; IS THIS PAGE PRELOADED?
BCS GTBT0 ; NO, SWAP IT IN
ADC ZCODE ; ELSE MAKE IT ABSOLUTE
BNE GTBT1 ; AND GIVE IT TO [MPCPNT]
GTBT0: LDX #0
STX ZPCFLG ; INVALIDATE [ZPC]
JSR PAGE ; AND GET ABS PAGE ADDR INTO [A]
GTBT1: STA MPCPNT+HI ; SET ABS PAGE ADDRESS
LDX #$FF
STX MPCFLG ; VALIDATE [MPCPNT]
INX ; = 0
STX MPCPNT+LO ; CLEAR LSB OF POINTER
GTBT2: LDY MPCL ; FETCH PAGE INDEX
LDA (MPCPNT),Y ; GET Z-BYTE
INC MPCL ; END OF PAGE YET?
BNE GTBT3 ; NO, EXIT
LDY #0
STY MPCFLG ; ELSE INVALIDATE [MPCPNT]
INC MPCM ; POINT [MPC] TO
BNE GTBT3 ; THE NEXT
INC MPCH ; Z-PAGE
GTBT3: TAY ; SET FLAGS
RTS ; AND RETURN
; ------------------------
; LOCATE A SWAPABLE Z-PAGE
; ------------------------
; ENTRY: TARGET Z-PAGE IN [A/Y] (9 BITS)
; EXIT: ABSOLUTE PAGE IN [A]
PAGE: STA TARGET+LO ; SAVE THE
STY TARGET+HI ; TARGET Z-PAGE HERE
; IS THIS Z-PAGE ALREADY PAGED IN?
LDX #0
STX ZPAGE ; START AT BUFFER #0
PG1: CMP PTABL,X ; LSB MATCHED?
BNE PG2 ; NO, TRY NEXT BUFFER
TYA ; ELSE CHECK
CMP PTABH,X ; TOP BIT
BEQ PG4 ; MATCHED! BUFFER IN [ZPAGE]
LDA TARGET+LO ; ELSE RESTORE LSB
PG2: INC ZPAGE ; UPDATE TALLY
INX
CPX PMAX ; OUT OF BUFFERS YET?
BCC PG1 ; NO, KEEP SEARCHING
; SWAP IN THE TARGET PAGE
PG3: JSR EARLY ; GET EARLIEST PAGE
LDX SWAP ; INTO [SWAP] & [X]
STX ZPAGE ; SAVE FOR LATER
LDA TARGET+LO ; ASSIGN THE TARGET PAGE
STA PTABL,X ; TO THE EARLIEST BUFFER
STA DBLOCK+LO ; ALSO GIVE IT TO ZDOS
LDA TARGET+HI ; SAME FOR TOP BIT
AND #%00000001 ; USE ONLY BIT 0
STA PTABH,X
STA DBLOCK+HI
TXA
CLC
ADC PAGE0 ; CALC ABS ADDR OF BUFFER
STA DBUFF+HI ; GIVE IT TO ZDOS
JSR GETDSK ; SWAP IN THE NEW PAGE
BCS DSKERR ; ERROR IF CARRY SET
; UPDATE THE TIMESTAMP
PG4: LDY ZPAGE ; GET THE BUFFER INDEX
LDA LRUMAP,Y ; GET THIS BUFFER'S STAMP
CMP STAMP ; SAME AS CURRENT STAMP?
BEQ PG8 ; YES, EXIT
INC STAMP ; UPDATE STAMP
BNE PG7 ; CONTINUE IF NO OVERFLOW
; HANDLE STAMP OVERFLOW
JSR EARLY ; GET EARLIEST STAMP INTO [LRU]
LDX #0 ; INIT INDEX
PG5: LDA LRUMAP,X ; GET A STAMP READING
BEQ PG6 ; EXIT IF ALREADY ZERO
SEC ; ELSE SUBTRACT OFF
SBC LRU ; THE EARLIEST TIMESTAMP
STA LRUMAP,X ; AND REPLACE THE STAMP
PG6: INX
CPX PMAX ; END OF SWAPPING SPACE?
BCC PG5 ; LOOP TILL ALL STAMPS FIXED
LDA #0 ; TURN BACK THE CLOCK
SEC ; TO REFLECT NEW
SBC LRU ; STAMP READING
STA STAMP
PG7: LDA STAMP ; FETCH STAMP
STA LRUMAP,Y ; STAMP TARGET PAGE WITH IT
PG8: LDA ZPAGE ; GET BUFFER INDEX
CLC ; MAKE IT
ADC PAGE0 ; ABSOLUTE
RTS ; AND RETURN IT IN [A]
; *** ERROR #14: DRIVE ACCESS ***
DSKERR: LDA #14
JMP ZERROR
; -------------------------
; LOCATE EARLIEST TIMESTAMP
; -------------------------
; EXIT: [LRU] - EARLIEST TIMESTAMP
; [SWAP] = INDEX TO EARLIEST BUFFER
EARLY: LDX #0 ; INIT INDEX
STX SWAP ; AND [SWAP]
LDA LRUMAP ; GET STAMP OF BUFFER #0
INX ; START COMPARE WITH BUFFER #1
EAR0: CMP LRUMAP,X ; IS THIS STAMP EARLIER THAN [A]?
BCC EAR1 ; NO, TRY NEXT STAMP
LDA LRUMAP,X ; ELSE FETCH EARLIER ENTRY
STX SWAP ; AND REMEMBER WHERE WE FOUND IT
EAR1: INX ; POINT TO NEXT STAMP
CPX PMAX ; OUT OF STAMPS YET?
BCC EAR0 ; LOOP TILL EMPTY
STA LRU ; SAVE EARLIEST STAMP HERE
RTS
; -------------------------
; POINT [MPC] TO V-ADDR [I]
; -------------------------
SETWRD: LDA I+LO
STA MPCL
LDA I+HI
STA MPCM
LDA #0
STA MPCH ; ZERO TOP BIT
STA MPCFLG ; INVALIDATE [MPC]
RTS
; ----------------------------
; GET Z-WORD AT [MPC] INTO [I]
; ----------------------------
GETWRD: JSR GETBYT
STA I+HI
JSR GETBYT
STA I+LO
RTS
END

308
atari/read.src Normal file
View File

@@ -0,0 +1,308 @@
PAGE
SBTTL "--- READ HANDLER ---"
; ----
; READ
; ----
; READ LINE INTO TABLE [ARG1]; PARSE INTO TABLE [ARG2]
ZREAD: JSR ZUSL ; UPDATE THE STATUS LINE
LDA ARG1+HI ; MAKE THE TABLE ADDRESSES
CLC ; ABSOLUTE
ADC ZCODE ; LSBS NEED NOT CHANGE
STA ARG1+HI
LDA ARG2+HI
CLC
ADC ZCODE
STA ARG2+HI
JSR INPUT ; READ LINE; RETURN LENGTH IN [A]
STA LINLEN ; SAVE # CHARS IN LINE
LDA #0
STA WRDLEN ; INIT # CHARS IN WORD COUNTER
LDY #1 ; POINT TO "# WORDS READ" SLOT
STA (ARG2),Y ; AND CLEAR IT ([A] = 0)
STY SOURCE ; INIT SOURCE TABLE PNTR ([Y] = 1)
INY ; = 2
STY RESULT ; AND RESULT TABLE POINTER
; MAIN LOOP STARTS HERE
READL: LDY #0 ; POINT TO "MAX # WORDS" SLOT
LDA (ARG2),Y ; AND READ IT
BEQ RLERR ; IF ENTRY IS ZERO, PATCH IT (BM 5/14/85)
CMP #60 ; IF ENTRY <= 59,
BCC RL0 ; CONTINUE
RLERR: LDA #59 ; FORCE # TOKENS
STA (ARG2),Y ; TO BE 59
RL0: INY ; (Y = 1) POINT TO "# WORDS READ" SLOT
CMP (ARG2),Y ; TOO MANY WORDS?
BCC RLEX ; EXIT IF SO (BM 5/1/85)
RL1: LDA LINLEN
ORA WRDLEN ; OUT OF CHARS AND WORDS?
BNE RL2 ; NOT YET
RLEX: RTS ; ELSE EXIT
RL2: LDA WRDLEN ; GET WORD LENGTH
CMP #6 ; 6 CHARS DONE?
BCC RL3 ; NO, KEEP GOING
JSR FLUSHW ; ELSE FLUSH REMAINDER OF WORD
RL3: LDA WRDLEN ; GET WORD LENGTH AGAIN
BNE READL2 ; CONTINUE IF NOT FIRST CHAR
; START A NEW WORD
LDX #5 ; CLEAR Z-WORD INPUT BUFFER
RLL: STA IN,X ; [A] = 0
DEX
BPL RLL
JSR EFIND ; GET BASE ADDRESS INTO [ENTRY]
LDA SOURCE ; STORE THE START POS OF THE WORD
LDY #3 ; INTO THE "WORD START" SLOT
STA (ENTRY),Y ; OF THE RESULT TABLE
TAY
LDA (ARG1),Y ; GET A CHAR FROM SOURCE BUFFER
JSR SIB ; IS IT A SELF-INSERTING BREAK?
BCS DOSIB ; YES IF CARRY WAS SET
JSR NORM ; IS IT A "NORMAL" BREAK?
BCC READL2 ; NO, CONTINUE
INC SOURCE ; ELSE FLUSH THE STRANDED BREAK
DEC LINLEN ; UPDATE # CHARS LEFT IN LINE
JMP READL ; AND LOOP
READL2: LDA LINLEN ; OUT OF CHARS YET?
BEQ READL3 ; LOOKS THAT WAY
LDY SOURCE
LDA (ARG1),Y ; ELSE GRAB NEXT CHAR
JSR BREAK ; IS IT A BREAK?
BCS READL3 ; YES IF CARRY WAS SET
LDX WRDLEN ; ELSE STORE THE CHAR
STA IN,X ; INTO THE INPUT BUFFER
DEC LINLEN ; ONE LESS CHAR IN LINE
INC WRDLEN ; ONE MORE IN WORD
INC SOURCE ; POINT TO NEXT CHAR IN SOURCE
JMP READL ; AND LOOP BACK
DOSIB: STA IN ; PUT THE BREAK INTO 1ST WORD SLOT
DEC LINLEN ; ONE LESS CHAR IN LINE
INC WRDLEN ; ONE MORE IN WORD BUFFER
INC SOURCE ; POINT TO NEXT SOURCE CHAR
READL3: LDA WRDLEN ; ANY CHARS IN WORD YET?
BEQ READL ; APPARENTLY NOT, SO LOOP BACK
JSR EFIND ; GET ENTRY ADDR INTO [ENTRY]
LDA WRDLEN ; GET ACTUAL LNGTH OF WORD
LDY #2 ; STORE IT IN "WORD LENGTH" SLOT
STA (ENTRY),Y ; OF THE CURRENT ENTRY
JSR CONZST ; CONVERT ASCII IN [IN] TO Z-STRING
JSR FINDW ; AND LOOK IT UP IN VOCABULARY
LDY #1
LDA (ARG2),Y ; FETCH THE # WORDS READ
CLC
ADC #1 ; INCREMENT IT
STA (ARG2),Y ; AND UPDATE
JSR EFIND ; MAKE [ENTRY] POINT TO ENTRY
LDY #0
STY WRDLEN ; CLEAR # CHARS IN WORD
LDA VALUE+HI ; GET MSB OF VOCAB ENTRY ADDRESS
STA (ENTRY),Y ; AND STORE IN 1ST SLOT OF ENTRY
INY
LDA VALUE+LO ; ALSO STORE LSB IN 2ND SLOT
STA (ENTRY),Y
LDA RESULT ; UPDATE THE
CLC ; RESULT TABLE POINTER
ADC #4 ; SO IT POINTS TO THE
STA RESULT ; NEXT ENTRY
JMP READL ; AND LOOP BACK
; -----------------------------------
; FIND BASE ADDR OF RESULT ENTRY SLOT
; -----------------------------------
EFIND: LDA ARG2+LO ; LSB OF RESULT TABLE BASE
CLC
ADC RESULT ; AND CURRENT POINTER
STA ENTRY+LO ; SAVE IN [ENTRY]
LDA ARG2+HI ; ALSO ADD MSB
ADC #0
STA ENTRY+HI
RTS
; ----------
; FLUSH WORD
; ----------
FLUSHW: LDA LINLEN ; ANY CHARS LEFT IN LINE?
BEQ FLEX ; NO, SCRAM
LDY SOURCE ; GET CURRENT CHAR POINTER
LDA (ARG1),Y ; AND GRAB A CHAR
JSR BREAK ; IS IT A BREAK?
BCS FLEX ; EXIT IF SO
DEC LINLEN ; ELSE UPDATE CHAR COUNT
INC WRDLEN ; AND WORD-CHAR COUNT
INC SOURCE ; AND CHAR POINTER
BNE FLUSHW ; AND LOOP BACK (ALWAYS)
FLEX: RTS
; ---------------------------------
; IS CHAR IN [A] ANY TYPE OF BREAK?
; ---------------------------------
BREAK: JSR SIB ; CHECK FOR A SIB FIRST
BCS FBRK ; EXIT NOW IF MATCHED
; ELSE FALL THROUGH ...
; --------------------------------
; IS CHAR IN [A] A "NORMAL" BREAK?
; --------------------------------
NORM: LDX #NBRKS-1 ; NUMBER OF "NORMAL" BREAKS
NBL: CMP BRKTBL,X ; MATCHED?
BEQ FBRK ; YES, EXIT
DEX
BPL NBL ; NO, KEEP LOOKING
CLC ; NO MATCH, CLEAR CARRY
RTS ; AND RETURN
; ------------------
; NORMAL BREAK CHARS
; ------------------
BRKTBL: DB "!?,." ; IN ORDER OF
DB $0D ; ASCENDING FREQUENCY
DB SPACE ; SPACE CHAR IS TESTED FIRST FOR SPEED
NBRKS EQU $-BRKTBL ; # NORMAL BREAKS
; ---------------------
; IS CHAR IN [A] A SIB?
; ---------------------
SIB: TAX ; SAVE TEST CHAR
LDY #0 ; 1ST BYTE IN VOCAB TABLE
LDA (VOCAB),Y ; HAS # SIBS
TAY ; USE AS AN INDEX
TXA ; RESTORE TEST CHAR
SBL: CMP (VOCAB),Y ; MATCHED?
BEQ FBRK ; YES, REPORT IT
DEY
BNE SBL ; ELSE KEEP LOOPING
CLC ; NO MATCH, SO
RTS ; EXIT WITH CARRY CLEAR
FBRK: SEC ; EXIT WITH CARRY SET
RTS ; IF MATCHED WITH A BREAK CHAR
; -----------------
; VOCABULARY SEARCH
; -----------------
; ENTRY: 4-BYTE TARGET Z-WORD IN [OUT]
; EXIT: ABS ENTRY ADDRESS IN [VALUE] IF FOUND;
; OTHERWISE [VALUE] = 0
FINDW: LDY #0 ; GET # SIBS
LDA (VOCAB),Y ; IN VOCAB TABLE
CLC ; INCREMENT IT
ADC #1 ; FOR PROPER ALIGNMENT
ADC VOCAB+LO ; NOW ADD THE BASE ADDR OF THE TABLE
STA VALUE+LO ; TO GET THE ACTUAL BASE ADDR
LDA VOCAB+HI ; OF THE VOCAB ENTRIES
ADC #0 ; WHICH IS SAVED
STA VALUE+HI ; IN [VALUE]
LDA (VALUE),Y ; GET # BYTES PER ENTRY ([Y] = 0)
STA ESIZE ; SAVE IT HERE
JSR INCVAL ; POINT TO NEXT BYTE
LDA (VALUE),Y ; GET # ENTRIES IN TABLE (MSB)
STA NENTS+HI ; AND STUFF IT IN [NENTS]
JSR INCVAL ; NEXT BYTE
LDA (VALUE),Y ; DON'T FORGET THE LSB!
STA NENTS+LO
JSR INCVAL ; [VALUE] NOW POINTS TO 1ST ENTRY
; BEGIN THE SEARCH!
FWL1: LDY #0
LDA (VALUE),Y ; GET 1ST BYTE OF ENTRY
CMP OUT ; MATCHED 1ST BYTE OF TARGET?
BNE WNEXT ; NO, SKIP TO NEXT WORD
INY
LDA (VALUE),Y
CMP OUT+1 ; 2ND BYTE MATCHED?
BNE WNEXT ; NOPE
INY
LDA (VALUE),Y
CMP OUT+2 ; 3RD BYTE?
BNE WNEXT ; SORRY ...
INY
LDA (VALUE),Y
CMP OUT+3 ; LAST BYTE
BEQ FWSUCC ; FOUND IT!
WNEXT: LDA ESIZE ; GET ENTRY SIZE
CLC ; AND ADD IT TO ENTRY ADDRESS
ADC VALUE+LO ; TO MAKE [VALUE]
STA VALUE+LO ; POINT TO THE NEXT ENTRY
BCC WNX
INC VALUE+HI
WNX: LDA NENTS+LO ; DECREMENT THE
SEC ; ENTRY COUNTER
SBC #1
STA NENTS+LO
BCS WNX1
DEC NENTS+HI
WNX1: ORA NENTS+HI ; KEEP SEARCHING
BNE FWL1 ; UNTIL COUNT IS ZERO
STA VALUE+LO
STA VALUE+HI
RTS ; THEN RETURN WITH [VALUE] = 0
; ENTRY MATCHED!
FWSUCC: LDA VALUE+HI ; CONVERT ABSOLUTE ENTRY ADDRESS
SEC ; IN [VALUE]
SBC ZCODE ; TO RELATIVE Z-ADDRESS
STA VALUE+HI ; LSB NEEDN'T CHANGE
RTS
END

345
atari/save.dip Normal file
View File

@@ -0,0 +1,345 @@
PAGE
SBTTL "--- SAVE/RESTORE ---"
; --------
; GRESTORE
; --------
GREST: JSR SRINIT ; INIT SCREEN, GET CR
LDA #0
STA GPCFLG ; INVALIDATE [GPC]
STA VPCFLG ; AND [VPC]
LDA #54
STA CURSOR ; CENTER TEXT
LDX #LOW RSTG
LDA #HIGH RSTG
LDY #RSTGL
JSR PRINT ; "RESTORING ..."
JSR READ ; READ 1ST BLOCK INTO [BUFFER]
BCS BADRD ; SCRAM IF ERROR
LDA BUFFER ; CHECK MSB
CMP GBEGIN+GID ; OF GAME ID
BNE BADRD ; SCRAM IF NO MATCH
LDA BUFFER+1 ; SAME FOR LSB
CMP GBEGIN+GID+1
BNE BADRD
LDA BUFFER+7 ; ALSO COMPARE SIZE SAVED
CMP PAGE0 ; TO CURRENT SIZE
BNE BADRD ; EXIT IF BAD
RST0: LDA BUFFER+2
STA GSP ; RESTORE [GSP]
LDA BUFFER+3
STA OLDGSP ; [OLDGSP]
LDA BUFFER+4
STA GPCL ; [GPCL]
LDA BUFFER+5
STA GPCH ; [GPCH]
LDA BUFFER+5
STA GPCH ; [GPCH]
LDA BUFFER+6
STA GPC0 ; [GPC0]
LDX #0
STX GPCFLG ; INVALIDATE [GPC]
STX VPCFLG ; AND [VPC]
INX ; = 1
STX STAMP ; RESET TIMESTAMP (?)
LDX #79 ; RESTORE [LOCALS], [CARGS], [CTYPES]
RST1: LDA BUFFER+8,X
STA LOCALS,X
DEX
BPL RST1
JSR READ ; RESTORE [GSTAKL]
BCS BADRD
JSR READ ; AND [GSTAKH]
BCS BADRD
LDA #LOW GBEGIN ; POINT [DBUFLO/HI]
STA DBUFLO ; TO PRELOAD
LDA #HIGH GBEGIN
STA DBUFHI
RST2: JSR READ ; READ A BLOCK
BCS BADRD ; EXIT IF ERROR
LDA DBUFHI ; END OF PRELOAD YET?
CMP PAGE0
BNE RST2 ; NO, KEEP READING
JSR NEWLIN ; CLEAR STATUS LINE
LDA #14
STA CURSOR ; CENTER TEXT
LDX #LOW GRD
LDA #HIGH GRD
LDY #GRDL
JSR PRINT ; "GAME RESTORED"
JSR GETGD ; "INSERT GAME DISK, PRESS START"
JMP PREDS ; SUCCEEDS
BADRD: JMP SRERR ; ELSE FAILS
; -----
; GSAVE
; -----
GSAVE: JSR SRINIT ; INIT SCREEN, GET CR
LDA #53
STA CURSOR ; CENTER TEXT
LDX #LOW SVG
LDA #HIGH SVG
LDY #SVGL
JSR PRINT ; "SAVING GAME ..."
LDA GBEGIN+GID ; SAVE 1ST
STA BUFFER ; AND
LDA GBEGIN+GID+1 ; 2ND BYTES OF
STA BUFFER+1 ; GAME ID WORD
LDA GSP
STA BUFFER+2 ; SAVE [GSP]
LDA OLDGSP
STA BUFFER+3 ; SAVE [OLDGSP]
LDA GPCL ; SAVE [GPC]
STA BUFFER+4
LDA GPCH
STA BUFFER+5
LDA GPC0
STA BUFFER+6
LDA PAGE0 ; SAVE SIZE OF PRELOADS
STA BUFFER+7
LDX #79 ; SAVE [LOCALS], [CARGS] & [CTYPES]
SV0: LDA LOCALS,X
STA BUFFER+8,X
DEX
BPL SV0
JSR WRITE ; WRITE [BUFFER] BLOCK
BCS SRERR
JSR WRITE ; WRITE [GSTAKL]
BCS SRERR
JSR WRITE ; WRITE [GSTAKH]
BCS SRERR
LDA #LOW GBEGIN ; POINT TO START OF PRELOADS
STA DBUFLO
LDA #HIGH GBEGIN
STA DBUFHI
SV1: JSR WRITE ; WRITE BLOCK
BCS SRERR ; SCRAM IF ERROR
LDA DBUFHI ; WRITTEN ALL OF
CMP PAGE0 ; PRELOAD(S)?
BNE SV1 ; NO, WRITE SOME MORE
JSR NEWLIN ; CLEAR STATUS LINE
LDA #14
STA CURSOR ; CENTER TEXT
LDX #LOW SCOM
LDA #HIGH SCOM
LDY #SCOML
JSR PRINT ; "SAVE COMPLETE"
JSR GETGD ; "INSERT GAME DISK"
JMP PREDS ; PREDICATE SUCCEEDS
; ------------------
; SAVE/RESTORE ERROR
; ------------------
SRERR: JSR NEWLIN ; CLEAR STATUS LINE
LDA #15
STA CURSOR ; CENTER TEXT
LDX #LOW DXX
LDA #HIGH DXX
LDY #DXXL
JSR PRINT ; "DISK ERROR!"
JSR GETGD ; "INSERT GAME DISK, PRESS START"
JMP PREDF ; PREDICATE FAILED
; -------------------
; WRITE BLOCK TO DISK
; -------------------
WRITE: LDA #$57 ; SIO "WRITE" COMMAND
BNE DDISK
; --------------------
; READ BLOCK FROM DISK
; --------------------
READ: LDA #$52 ; SIO "READ" COMMAND
DDISK: STA DCOMND ; SET READ/WRITE MODE
LDA #1 ; ALWAYS USE
STA DUNIT ; DRIVE #1
JSR DSKINV ; ACCESS 1ST HALF
LDA DSTATS
BMI BADISK ; EXIT IF ERROR
JSR NEXTSC ; SET UP NEXT ACCESS
JSR DSKINV ; ACCESS 2ND HALF
LDA DSTATS
BMI BADISK ; EXIT IF ERROR
JSR NEXTSC ; SET UP NEXT ACCESS
CLC ; CARRY CLEAR = OKAY
RTS
BADISK: SEC ; CARRY SET = BAD I/O
RTS
; ---------------------------
; POINT TO NEXT SECTOR/BUFFER
; ---------------------------
NEXTSC: INC DAUX1 ; LSB OF SECTOR ID
BNE NXC
INC DAUX2 ; MSB
NXC: LDA DBUFLO ; POINT TO 2ND HALF
CLD ; OF BUFFER
CLC
ADC #$80
STA DBUFLO
LDA DBUFHI
ADC #0
STA DBUFHI
RTS
; --------------------
; SAVE & RESTORE TEXT
; IN ATARI SCREEN CODE
; --------------------
; INSERT SAVE DISK, PRESS START
SAVEM: DB 41,110,115,101,114,116,0
DB 51,33,54,37,0
DB 100,105,115,107,12,0
DB 112,114,101,115,115,0
DB 179,180,161,178,180,0
SAVEML EQU $-SAVEM
; INSERT GAME DISK, PRESS START
RESTM: DB 41,110,115,101,114,116,0
DB 39,33,45,37,0
DB 100,105,115,107,12,0
DB 112,114,101,115,115,0
DB 179,180,161,178,180,0
RESTML EQU $-RESTM
; SAVING GAME ...
SVG: DB 51,97,118,105,110,103,0
DB 103,97,109,101,0,14,14,14,0
SVGL EQU $-SVG
; RESTORING ...
RSTG: DB 50,101,115,116,111,114,105,110,103,0,14,14,14,0
RSTGL EQU $-RSTG
; DISK ERROR!
DXX: DB 36,41,51,43,0,37,50,50,47,50,1,0
DXXL EQU $-DXX
; SAVE COMPLETE
SCOM: DB 51,33,54,37,0,35,47,45,48,44,37,52,37,0
SCOML EQU $-SCOM
; GAME RESTORED
GRD: DB 39,33,45,37,0,50,37,51,52,47,50,37,36,0
GRDL EQU $-GRD
; ------------------------
; INIT SAVE/RESTORE SCREEN
; ------------------------
SRINIT: JSR STATUS ; SET UP STATUS LINE
LDA #3
STA SOUNDR ; ENABLE NOISY I/O
LDA #6
STA CURSOR ; CENTER TEXT
LDX #LOW SAVEM
LDA #HIGH SAVEM
LDY #SAVEML
JSR PRINT ; "INSERT SAVE DISK ..."
LDA #1 ; POINT [DAUX1/2] TO SECTOR 1
STA DAUX1
LDA #0
STA DAUX2
LDA #LOW BUFFER ; AND TO [BUFFER]
STA DBUFLO
LDA #HIGH BUFFER
STA DBUFHI
; FALL THROUGH ...
; -----------------
; WAIT FOR "START"
; -----------------
GETST: JSR SND3 ; "TING"
GST0: LDA CONSOL
CMP #6
BNE GST0
GST1: LDA CONSOL
CMP #7
BNE GST1
RTS
; --------------------
; PROMPT FOR GAME DISK
; --------------------
GETGD: LDA #46
STA CURSOR ; CENTER LINE
LDX #LOW RESTM
LDA #HIGH RESTM
LDY #RESTML
JSR PRINT ; "INSERT GAME DISK ..."
JSR GETST ; GET START KEY
LDX #LOW DL2 ; SWITCH BACK TO
LDA #HIGH DL2 ; FULL-SCREEN DLIST
STX DLTOP+LO
STA DLTOP+HI
STX SDLSTL+LO
STA SDLSTL+HI
LDA #0
STA SOUNDR ; DISABLE NOISY I/O
RTS
END

108
atari/sound.dip Normal file
View File

@@ -0,0 +1,108 @@
PAGE
SBTTL "GAME-DEPENDENT SOUND LIBRARY (ATARI FOOBLITSKY)"
; ----------------------------
; GAME-DEPENDENT SOUND LIBRARY
; ----------------------------
STABLE: DW SND1
DW SND2
DW SND3
DW SND4
SOUNDS EQU 4 ; # SOUNDS IN LIBRARY
; ----------------
; SOUND #1: "BOOP"
; ----------------
SND1: LDX #150 ; FREQUENCY
LDA #252 ; DURATION (4 JIFFIES)
LDY #$AE ; FULL VOLUME, NO DISTORTION
BNE NOISE
; -----------------
; SOUND #2: "CLICK"
; -----------------
SND2: LDX #25 ; FREQUENCY
LDA #255 ; DURATION (1 JIFFY)
LDY #$AE ; FULL VOLUME, NO DISTORTION
; FALL THROUGH ...
NOISE: STX AUDF1
STY AUDC1
STA RTCLOK ; START TIMER
S1L: LDA RTCLOK
BNE S1L
STA AUDC1 ; STOP SOUND
RTS
; ----------------
; SOUND #3: "TING"
; ----------------
SND3: LDA #10 ; FREQUENCY
STA AUDF1
LDA #$AE ; FULL, PURE TONE
STA AUDC1
LDA #251 ; 5-JIFFY SUSTAIN
STA RTCLOK
S3L1: LDA RTCLOK
BNE S3L1
; DECAY TO ZERO VOLUME
LDX #$0E ; VOLUME INDEX
S3L2: TXA
ORA #$A0 ; SUPERIMPOSE DISTORTION (PURE)
STA AUDC1
LDA #252 ; WAIT 4 JIFFIES ON EACH LEVEL
STA RTCLOK
S3L3: LDA RTCLOK
BNE S3L3
DEX
DEX ; LOOP BACK TILL
BNE S3L2 ; NO MORE VOLUME
STX AUDC1 ; STOP TONE
RTS
; ----------------
; SOUND #4: "RAZZ"
; ----------------
SND4: LDA #100 ; FREQUENCY
STA AUDF1
LDA #$2E ; LOUD, DISTORTED TONE
STA AUDC1
LDA #251 ; 5-JIFFY SUSTAIN
STA RTCLOK
S4L1: LDA RTCLOK
BNE S4L1
; DECAY TO ZERO VOLUME
LDX #$0E ; VOLUME INDEX
S4L2: TXA
ORA #$20 ; SUPERIMPOSE DISTORTION
STA AUDC1
LDA #252 ; WAIT 4 JIFFIES ON EACH LEVEL
STA RTCLOK
S4L3: LDA RTCLOK
BNE S4L3
DEX
DEX ; LOOP BACK TILL
BNE S4L2 ; NO MORE VOLUME
STX AUDC1 ; STOP TONE
RTS
END

339
atari/subs.dip Normal file
View File

@@ -0,0 +1,339 @@
PAGE
SBTTL "--- OPCODE SUPPORT SUBROUTINES ---"
; -----------------------
; FETCH A SHORT IMMEDIATE
; -----------------------
GETSHT: LDA #0 ; CLEAR MSB OF [VALUE]
BEQ GLG ; AND GRAB LSB
; ----------------------
; FETCH A LONG IMMEDIATE
; ----------------------
GETLNG: JSR NEXTPC ; GRAB MSB
GLG: STA VALUE+HI ; STORE IT
JSR NEXTPC ; GRAB LSB
STA VALUE+LO ; STORE THAT TOO
RTS
; ----------------
; FETCH A VARIABLE
; ----------------
; FROM WITHIN AN OPCODE (VARIABLE ID IN [A])
VARGET: TAX ; IF NON-ZERO,
BNE GETVR1 ; ACCESS A VARIABLE
JSR POPVAL ; ELSE PULL VAR OFF Z-STACK
JMP PSHVAL ; WITHOUT ALTERING STACK
; FROM THE MAIN LOOP (ID BYTE IN Z-CODE)
GETVAR: JSR NEXTPC ; GRAB VAR-TYPE BYTE
BEQ POPVAL ; VALUE IS ON Z-STACK
; IS VARIABLE LOCAL OR GLOBAL?
GETVR1: CMP #$10 ; IF >= 16,
BCS GETVRG ; IT'S GLOBAL
; HANDLE A LOCAL VARIABLE
GETVRL: SEC
SBC #1 ; FORM A ZERO-ALIGNED
ASL A ; WORD INDEX
TAX ; INTO THE [LOCALS]
LDA LOCALS+LO,X ; GRAB LSB
STA VALUE+LO
LDA LOCALS+HI,X ; AND MSB
STA VALUE+HI
RTS
; HANDLE A GLOBAL VARIABLE
GETVRG: JSR GVCALC ; GET ADDRESS OF GLOBAL INTO [I]
LDA (I),Y ; MSB OF GLOBAL ([Y] = 0)
STA VALUE+HI
INY ; = 1
LDA (I),Y ; LSB OF GLOBAL
STA VALUE+LO ; SAVE IT
RTS ; AND WE'RE DONE
; ----------------------------------
; POP G-STACK INTO [VALUE] AND [X/A]
; ----------------------------------
POPVAL: DEC GSP
BEQ UNDER ; UNDERFLOW IF ZERO!
LDY GSP ; READ STACK POINTER
LDX GSTAKL,Y ; GRAB LSB OF STACK VALUE
STX VALUE+LO ; GIVE TO [VALUE]
LDA GSTAKH,Y ; ALSO GRAB MSB
STA VALUE+HI ; A SIMILAR FATE
RTS
; *** ERROR #6: G-STACK UNDERFLOW ***
UNDER: LDA #6
JMP GERROR
; -----------------------
; PUSH [VALUE] TO G-STACK
; -----------------------
PSHVAL: LDX VALUE+LO
LDA VALUE+HI
; FALL THROUGH ...
; ---------------------
; PUSH [X/A] TO G-STACK
; ---------------------
PSHXA: LDY GSP
STA GSTAKH,Y
TXA
STA GSTAKL,Y
INC GSP
BEQ OVER ; OVERFLOW IF ZEROED!
RTS
; *** ERROR #7: G-STACK OVERFLOW ***
OVER: LDA #7
JMP GERROR
; --------------
; RETURN A VALUE
; --------------
; FROM WITHIN AN OPCODE (VARIABLE ID IN [A])
VARPUT: TAX ; IF ZERO,
BNE PUTVR1
DEC GSP ; FLUSH TOP WORD OFF STACK
BNE PSHVAL ; AND REPLACE WITH [VALUE]
BEQ UNDER ; ERROR IF ZSP BECAME ZERO!
; RETURN A ZERO
RET0: LDA #0
; RETURN BYTE IN [A]
PUTBYT: STA VALUE+LO
LDA #0
STA VALUE+HI ; CLEAR MSB
; RETURN [VALUE]; VARIABLE ID IN NEXT Z-BYTE
PUTVAL: JSR NEXTPC ; GET VAR-TYPE BYTE
BEQ PSHVAL ; VALUE GOES TO STACK IF ZERO
; LOCAL OR GLOBAL VARIABLE?
PUTVR1: CMP #$10 ; IF >= 16,
BCS PUTVLG ; IT'S GLOBAL
; PUT A LOCAL VARIABLE
PUTVLL: SEC
SBC #1 ; FORM A ZERO-ALIGNED
ASL A ; WORD INDEX
TAX ; INTO [LOCALS]
LDA VALUE+LO ; GRAB LSB
STA LOCALS+LO,X ; SAVE IN LOCAL TABLE
LDA VALUE+HI ; DO SAME TO
STA LOCALS+HI,X ; MSB
RTS
; PUT A GLOBAL VARIABLE
PUTVLG: JSR GVCALC ; GET ADDR OF GLOBAL INTO [I]
LDA VALUE+HI ; GET MSB
STA (I),Y ; STORE AS 1ST BYTE ([Y] = 0)
INY ; [Y] = 1
LDA VALUE+LO ; NOW GET LSB
STA (I),Y ; STORE AS 2ND BYTE
RTS
; -----------------------
; CALC GLOBAL WORD OFFSET
; -----------------------
; ENTRY: VAR-ID BYTE (16-255) IN [A]
; EXIT: ADDRESS OF GLOBAL VAR IN [VAL]
; [Y] = 0 FOR INDEXING
GVCALC: SEC
SBC #$10 ; FORM A ZERO-ALIGNED INDEX
LDY #0 ; MAKE SURE MSB OF OFFSET AND [Y]
STY I+HI ; ARE CLEARED
ASL A ; MULTIPLY OFFSET BY 2
ROL I+HI ; TO WORD-ALIGN IT
CLC ; TO ADDRESS OF GLOBAL TABLE
ADC GLOBAL+LO ; TO FORM THE ABSOLUTE
STA I+LO ; ADDRESS OF THE
LDA I+HI ; DESIRED GLOBAL VARIABLE
ADC GLOBAL+HI ; STORE ADDRESS BACK IN [I]
STA I+HI ; AS A POINTER
WCEX: RTS
; ---------------
; PREDICATE FAILS
; ---------------
PREDF: JSR NEXTPC ; GET 1ST BRANCH BYTE
BPL PREDB ; BRANCH IF BIT 7 CLEAR
; -----------------------
; IGNORE PREDICATE BRANCH
; -----------------------
; ENTRY: 1ST BRANCH BYTE IN [A]
PREDNB: AND #%01000000 ; TEST BIT 6
BNE WCEX ; SHORT BRANCH IF SET
JMP NEXTPC ; ELSE SKIP OVER 2ND BRANCH BYTE
; ------------------
; PREDICATE SUCCEEDS
; ------------------
PREDS: JSR NEXTPC ; GET 1ST BRANCH BYTE
BPL PREDNB ; DON'T BRANCH IF BIT 7 CLEAR
; --------------------------
; PERFORM A PREDICATE BRANCH
; --------------------------
; ENTRY: 1ST PRED BYTE IN [A]
PREDB: TAX ; COPY FOR LATER
AND #%01000000 ; LONG OR SHORT BRANCH?
BEQ PREDLB ; LONG IF BIT 6 IS CLEAR
; HANDLE A SHORT BRANCH
TXA ; RESTORE PRED BYTE
AND #%00111111 ; FORM SHORT OFFSET
STA VALUE+LO ; USE AS LSB OF BRANCH OFFSET
LDA #0
STA VALUE+HI ; MSB OF OFFSET IS ZERO
BEQ PREDB1 ; DO THE BRANCH
; HANDLE A LONG BRANCH
PREDLB: TXA ; RESTORE 1ST PRED BYTE
AND #%00111111 ; FORM MSB OF OFFSET
TAX ; SAVE HERE FOR REFERENCE
AND #%00100000 ; CHECK SIGN OF 14-BIT VALUE
BEQ DOB2 ; POSITIVE IF ZERO, USE [X] FOR MSB
TXA ; ELSE RESTORE BYTE
ORA #%11100000 ; EXTEND SIGN BIT
TAX ; BACK HERE FOR STORAGE
DOB2: STX VALUE+HI
JSR NEXTPC ; FETCH LSB OF 14-BIT OFFSET
STA VALUE+LO
; BRANCH TO Z-ADDRESS IN [VALUE]
PREDB1: LDA VALUE+HI ; CHECK MSB OF OFFSET
BNE PREDB3 ; DO BRANCH IF NZ
LDA VALUE+LO ; IF LSB IS NON-ZERO,
BNE PREDB2 ; MAKE SURE IT ISN'T 1
JMP GRFALS ; ELSE DO AN "RFALSE" IF [VALUE] = 0
PREDB2: CMP #1 ; IF OFFSET = 1
BNE PREDB3
JMP GRTRUE ; DO AN "RTRUE"
; ENTRY POINT FOR "JUMP"
PREDB3: JSR DECVAL ; CALC [VALUE]-2
JSR DECVAL
;***
LDA VALUE+HI
LDX VALUE+LO
JSR ADDGPC
LDA VALUE+HI ; EXTEND SIGN
AND #$80
CLC
ADC GPCH
STA GPCH
;***
; LDA VALUE+LO ; GET LSB OF OFFSET
; CLC
; ADC GPCL ; ADD LSB OF GPC
; BCC PREDB5 ; IF OVERFLOWED,
; INC VALUE+HI ; UPDATE MSB OF OFFSET
;PREDB5: STA GPCL ; UPDATE ZPCL
; LDA VALUE+HI ; IF MSB IS ZERO,
; BEQ GNOOP ; PAGE IS STILL VALID
; CLC
; ADC GPCH
; STA GPCH ; ELSE SWITCH PAGES
; LDA #0 ; INVALIDATE [GPC]
; STA GPCFLG
; FALL THROUGH ...
; ----
; NOOP
; ----
GNOOP: RTS
; -----------------
; INCREMENT [VALUE]
; -----------------
INCVAL: INC VALUE+LO
BNE IVX
INC VALUE+HI
IVX: RTS
; -----------------
; DECREMENT [VALUE]
; -----------------
DECVAL: LDA VALUE+LO
SEC
SBC #1
STA VALUE+LO
BCS DVX
DEC VALUE+HI
DVX: RTS
; ----------------------
; MOVE [ARG1] TO [VALUE]
; ----------------------
A12VAL: LDA ARG1+LO
STA VALUE+LO
LDA ARG1+HI
STA VALUE+HI
RTS
END

347
atari/subs.src Normal file
View File

@@ -0,0 +1,347 @@
PAGE
SBTTL "--- OPCODE SUPPORT SUBROUTINES ---"
; -----------------------
; FETCH A SHORT IMMEDIATE
; -----------------------
GETSHT: LDA #0 ; MSB IS ZERO
BEQ GETV ; FETCH LSB FROM Z-CODE
; ----------------------
; FETCH A LONG IMMEDIATE
; ----------------------
GETLNG: JSR NEXTPC ; GRAB MSB
GETV: STA VALUE+HI
JSR NEXTPC ; GRAB LSB
STA VALUE+LO
RTS
; ----------------
; FETCH A VARIABLE
; ----------------
; FROM INSIDE AN OPCODE (VARIABLE ID IN [A])
VARGET: TAX ; IF NON-ZERO,
BNE GETVR1 ; ACCESS A VARIABLE
JSR POPVAL ; ELSE PULL VAR OFF Z-STACK
JMP PSHVAL ; WITHOUT ALTERING STACK
; FROM THE MAIN LOOP (VARIABLE ID IN Z-CODE)
GETVAR: JSR NEXTPC ; GRAB VAR-TYPE BYTE
BEQ POPVAL ; VALUE IS ON Z-STACK
; IS VARIABLE LOCAL OR GLOBAL?
GETVR1: CMP #$10 ; IF >= 16,
BCS GETVRG ; IT'S GLOBAL
; HANDLE A LOCAL VARIABLE
GETVRL: SEC
SBC #1 ; FORM A ZERO-ALIGNED
ASL A ; WORD INDEX
TAX ; INTO THE [LOCALS] TABLE
LDA LOCALS+LO,X ; GRAB LSB
STA VALUE+LO
LDA LOCALS+HI,X ; AND MSB
STA VALUE+HI
RTS
; HANDLE A GLOBAL VARIABLE
GETVRG: JSR GVCALC ; GET ADDRESS OF GLOBAL INTO [I]
LDA (I),Y ; MSB OF GLOBAL ([Y] = 0)
STA VALUE+HI
INY ; = 1
LDA (I),Y ; LSB OF GLOBAL
STA VALUE+LO ; SAVE IT
RTS ; AND WE'RE DONE
; ----------------------------------
; POP Z-STACK INTO [VALUE] AND [X/A]
; ----------------------------------
POPVAL: DEC ZSP
BEQ UNDER ; UNDERFLOW IF ZERO!
LDY ZSP ; READ STACK POINTER
LDX ZSTAKL,Y ; GRAB LSB OF STACK VALUE
STX VALUE+LO ; GIVE TO [VALUE]
LDA ZSTAKH,Y ; ALSO GRAB MSB
STA VALUE+HI ; A SIMILAR FATE
RTS
; *** ERROR #5 -- Z-STACK UNDERFLOW ***
UNDER: LDA #5
JMP ZERROR
; -----------------------
; PUSH [VALUE] TO Z-STACK
; -----------------------
PSHVAL: LDX VALUE+LO
LDA VALUE+HI
; ---------------------
; PUSH [X/A] TO Z-STACK
; ---------------------
PUSHXA: LDY ZSP ; READ STACK POINTER
STA ZSTAKH,Y ; PUSH MSB IN [A]
TXA
STA ZSTAKL,Y ; AND LSB IN [X]
INC ZSP ; UPDATE Z-STACK POINTER
BEQ OVER ; OVERFLOW IF ZEROED!
RTS
; *** ERROR #6 -- Z-STACK OVERFLOW ***
OVER: LDA #6
JMP ZERROR
; --------------
; RETURN A VALUE
; --------------
; FROM WITHIN AN OPCODE (VARIABLE ID IN [A])
VARPUT: TAX ; IF ZERO,
BNE PUTVR1
DEC ZSP ; FLUSH TOP WORD OFF STACK
BNE PSHVAL ; AND REPLACE WITH [VALUE]
BEQ UNDER ; ERROR IF [ZSP] BECAME ZERO!
; RETURN A ZERO
RET0: LDA #0
; RETURN BYTE IN [A]
PUTBYT: STA VALUE+LO
LDA #0
STA VALUE+HI ; CLEAR MSB
; RETURN [VALUE]
PUTVAL: JSR NEXTPC ; GET VARIABLE ID BYTE
BEQ PSHVAL ; [VALUE] GOES TO Z-STACK
; LOCAL OR GLOBAL VARIABLE?
PUTVR1: CMP #$10 ; IF >= 16,
BCS PUTVLG ; IT'S GLOBAL
; PUT A LOCAL VARIABLE
PUTVLL: SEC
SBC #1 ; FORM A ZERO-ALIGNED
ASL A ; WORD INDEX
TAX ; INTO THE [LOCALS] TABLE
LDA VALUE+LO ; GRAB LSB
STA LOCALS+LO,X ; SAVE IN LOCAL TABLE
LDA VALUE+HI ; DO SAME TO
STA LOCALS+HI,X ; MSB
RTS
; RETURN A GLOBAL VARIABLE
PUTVLG: JSR GVCALC
LDA VALUE+HI ; GET MSB
STA (I),Y ; STORE AS 1ST BYTE ([Y] = 0)
INY ; = 1
LDA VALUE+LO ; NOW GET LSB
STA (I),Y ; STORE AS 2ND BYTE
RTS
; -----------------------
; CALC GLOBAL WORD OFFSET
; -----------------------
; ENTRY: VAR-ID BYTE (16-255) IN [A]
; EXIT: ABSOLUTE ADDRESS OF GLOBAL VAR IN [I]
; [Y] = 0 FOR INDEXING
GVCALC: SEC
SBC #$10 ; FORM A ZERO-ALIGNED INDEX
LDY #0 ; MAKE SURE MSB OF OFFSET AND [Y]
STY I+HI ; ARE CLEARED
ASL A ; MULTIPLY OFFSET BY 2
ROL I+HI ; TO WORD-ALIGN IT
CLC ; ADD OFFSET TO ADDR OF GLOBAL TABLE
ADC GLOBAL+LO ; TO FORM THE ABSOLUTE
STA I+LO ; ADDRESS OF THE
LDA I+HI ; DESIRED GLOBAL VARIABLE
ADC GLOBAL+HI ; STORE ADDRESS BACK IN [VAL]
STA I+HI ; AS A POINTER
WCEX: RTS
; ---------------
; PREDICATE FAILS
; ---------------
PREDF: JSR NEXTPC ; GET 1ST BRANCH BYTE
BPL PREDB ; DO BRANCH IF BIT 7 OFF
; -----------------------
; IGNORE PREDICATE BRANCH
; -----------------------
; ENTRY: 1ST BRANCH BYTE IN [A]
PREDNB: AND #%01000000 ; TEST BIT 6
BNE WCEX ; SHORT BRANCH IF SET
JMP NEXTPC ; ELSE SKIP OVER 2ND BRANCH BYTE
; ------------------
; PREDICATE SUCCEEDS
; ------------------
PREDS: JSR NEXTPC ; GET 1ST BRANCH BYTE
BPL PREDNB ; DON'T BRANCH IF BIT 7 CLEAR
; --------------------------
; PERFORM A PREDICATE BRANCH
; --------------------------
; ENTRY: 1ST PRED BYTE IN [A]
PREDB: TAX ; SAVE HERE
AND #%01000000 ; LONG OR SHORT BRANCH?
BEQ PREDLB ; LONG IF BIT 6 IS CLEAR
; HANDLE A SHORT BRANCH
TXA ; RESTORE PRED BYTE
AND #%00111111 ; FORM SHORT OFFSET
STA VALUE+LO ; USE AS LSB OF BRANCH OFFSET
LDA #0
STA VALUE+HI ; MSB OF OFFSET IS ZERO
BEQ PREDB1 ; DO THE BRANCH
; HANDLE A LONG BRANCH
PREDLB: TXA ; RESTORE 1ST PRED BYTE
AND #%00111111 ; FORM MSB OF OFFSET
TAX ; SAVE HERE FOR REFERENCE
AND #%00100000 ; CHECK SIGN OF 14-BIT VALUE
BEQ DOB2 ; POSITIVE IF ZERO, SO USE [X]
TXA ; ELSE RESTORE BYTE
ORA #%11100000 ; EXTEND THE SIGN BIT
TAX ; BACK HERE FOR STORAGE
DOB2: STX VALUE+HI
JSR NEXTPC ; FETCH LSB OF 14-BIT OFFSET
STA VALUE+LO
; BRANCH TO Z-ADDRESS IN [VALUE]
PREDB1: LDA VALUE+HI ; CHECK MSB OF OFFSET
BNE PREDB3 ; DO BRANCH IF NZ
LDA VALUE+LO ; IF LSB IS NON-ZERO,
BNE PREDB2 ; MAKE SURE IT ISN'T 1
JMP ZRFALS ; ELSE DO AN "RFALSE"
PREDB2: CMP #1 ; IF OFFSET = 1
BNE PREDB3
JMP ZRTRUE ; DO AN "RTRUE"
; ENTRY POINT FOR "JUMP"
PREDB3: JSR DECVAL ; SUBTRACT 2 FROM THE OFFSET
JSR DECVAL ; IN [VALUE]
LDA #0 ; CLEAR THE MSB
STA I+HI ; OF [I]
LDA VALUE+HI ; MAKE MSB OF OFFSET
STA I+LO ; THE LSB OF [I]
ASL A ; EXTEND THE SIGN OF OFFSET
ROL I+HI ; INTO MSB OF [I]
LDA VALUE+LO ; GET LSB OF OFFSET
CLC
ADC ZPCL ; ADD LOW 8 BITS OF ZPC
BCC PREDB5 ; IF OVERFLOWED,
INC I+LO ; UPDATE UPPER 9 BITS
BNE PREDB5
INC I+HI
PREDB5: STA ZPCL ; UPDATE ZPC
LDA I+LO ; IF UPPER 9 BITS ARE ZERO,
ORA I+HI ; NO NEED TO CHANGE PAGES
BEQ ZNOOP
LDA I+LO ; ELSE CALC NEW UPPER BITS
CLC
ADC ZPCM
STA ZPCM
LDA I+HI
ADC ZPCH
AND #%00000001 ; USE ONLY BIT 0
STA ZPCH
LDA #0
STA ZPCFLG ; [ZPC] NO LONGER VALID
; FALL THROUGH ...
; ----
; NOOP
; ----
ZNOOP: RTS
; -----------------
; DECREMENT [VALUE]
; -----------------
DECVAL: LDA VALUE+LO
SEC
SBC #1
STA VALUE+LO
BCS DVX
DEC VALUE+HI
DVX: RTS
; -----------------
; INCREMENT [VALUE]
; -----------------
INCVAL: INC VALUE+LO
BNE IVX
INC VALUE+HI
IVX: RTS
; ----------------------
; MOVE [ARG1] TO [VALUE]
; ----------------------
A12VAL: LDA ARG1+LO
STA VALUE+LO
LDA ARG1+HI
STA VALUE+HI
RTS
END

344
atari/warm.dip Normal file
View File

@@ -0,0 +1,344 @@
PAGE
SBTTL "--- WARMSTART ROUTINE ---"
; ---------
; WARMSTART
; ---------
WARM: LDA #0 ; CLEAR ALL Z-PAGE VARIABLES
LDX #ZSTART
CLRZ: STA 0,X
INX
; CPX #ZEND ; NOT NEEDED FOR ATARI
BNE CLRZ
; CLEAR THE MEMORY, LRU & SWAPPING MAPS
TAX ; = 0
CLRT: STA MEMMAP,X
STA PAGMAP,X
INX
BNE CLRT
INC GSP ; INIT G-STACK POINTERS
INC OLDGSP ; TO 1
INC STAMP ; 1ST TIMESTAMP IS 1
LDA #40 ; SET DEFAULT CLIPPING PARAMETERS
STA WINDX2
STA WINDW ; DEFAULT WINDOW WIDTH
LDA #24
STA WINDY2
STA WINDH ; DEFAULT WINDOW HEIGHT
; FETCH 1ST BLOCK OF G-PRELOAD
LDA #HIGH GBEGIN
STA GCODE ; 1ST PAGE OF G-PRELOAD
STA DBUFF+HI ; LSB OF [DBUFF] IS ALWAYS ZERO
DEC ISTART ; (= $FF) FORCE LOAD FROM G-FILE
JSR GETDSK ; GRAB G-BLOCK #0 (G-PRELOAD HEADER)
; EXTRACT DATA FROM G-PRELOAD HEADER
LDX GBEGIN+GEND ; END OF PRELOAD (MSB)
INX ; MAKE IT AT LEAST 1
STX GPURE ; 1ST VIRTUAL PAGE OF "PURE" G-CODE
TXA
;***
ASL A ; * 2 FOR 512 BYTE PAGES
BCS NOGRAM ; IT WOULD BE BAD IF CARRY WERE SET
;***
; CLC
ADC GCODE ; ABSOLUTE END OF G-PRELOAD
STA ICODE+HI ; IS ABSOLUTE START OF I-PRELOAD
LDA #INTRP ; SET INTERPRETER VERSION
STA GBEGIN+IVERS ; FOR GAME
JSR MEMTOP ; GET TOP FREE PAGE INTO [A]
CMP ICODE+HI ; ENOUGH ROOM FOR G-PRELOAD?
BEQ NOGRAM
BCS GETLEN ; ONLY IF [MEMTOP] >= [ICODE]
; *** ERROR #0: GAME PRELOAD TOO BIG ***
NOGRAM: LDA #0
JMP GERROR
; CALC VIRTUAL ADDRESS OF I-FILE
GETLEN: LDX GBEGIN+GLEN ; MSB OF G-CODE LENGTH
INX
STX ISTART ; 1ST VIRTUAL PAGE OF I-FILE
; FETCH THE REST OF THE G-PRELOAD
GPGET: LDA DBLOCK
CMP GPURE
BCS IHEAD
JSR GETDSK
JMP GPGET
; NOW GET THE I-FILE HEADER
IHEAD: LDA ISTART ; POINT TO 1ST BLOCK
STA DBLOCK ; OF IMAGE FILE
LDA ICODE+HI ; TELL GROS
STA DBUFF+HI ; WHERE TO PUT IT
JSR GETDSK ; AND GET IT!
; EXTRACT DATA FROM I-FILE HEADER
LDY #IEND ; "END OF I-PRELOAD" POINTER (MSB)
LDA (ICODE),Y
TAX ; COPY IT HERE
INX ; POINT TO NEXT PAGE
TXA
CLC
ADC ISTART ; ADD 1ST V-PAGE OF I-FILE
STA IPURE ; TO GET V-PAGE OF "PURE" I-CODE
TXA
;***
ASL A ; * 2 FOR 512 BYTE PAGES
BCS ITOBIG ; AGAIN IT WOULD BE BAD IF CARRY WERE SET
;***
; CLC
ADC ICODE+HI ; ADD BASE ADDR OF I-PRELOAD
STA PAGE0 ; TO GET BASE PAGE OF SWAPPING SPACE
JSR MEMTOP ; GET TOP FREE PAGE INTO [A] AGAIN
SEC
SBC PAGE0 ; CALC # PAGES IN SWAPPING SPACE
CMP #16 ; MUST HAVE AT LEAST 2K
BCS ENOUGH ; OF SWAPPING SPACE
; *** ERROR #1: IMAGE PRELOAD TOO BIG ***
ITOBIG: LDA #1
JMP GERROR
ENOUGH: TAX ; CHECK SIZE OF PAGING SPACE
BPL NOUGH ; MUST BE NO LARGER
LDA #$7E ; THAN 32K!
;***
NOUGH: LSR A ; DIVIDE !RAM! PAGES/2 TO GET #/BUFFERS
****
STA PMAX ; ESTABLISH # SWAPPING PAGES
; GRAB THE REST OF THE I-PRELOAD
GETIP: LDA DBLOCK
CMP IPURE
BCS GCALC
JSR GETDSK
JMP GETIP
; CALC ADDRESS OF GLOBAL VARIABLE TABLE
;GCALC: LDA GBEGIN+GGLOB ; MSB OF GLOBAL VARS
; CLC
; ADC GCODE ; MAKE IT ABSOLUTE
; STA GLOBAL+HI
; LDA GBEGIN+GGLOB+1 ; LSB NEEDN'T CHANGE
; STA GLOBAL+LO
;***
;-----------------------------------------------------------
; [GGLOB] IS A VIRTUAL WORD POINTER TO THE GLOBAL TABLE
; MAKE [GLOBAL] A !RAM! ABSOLUTE POINTER TO THE GLOBAL TABLE
;
; WE MULTIPLY [GGLOB]*2 TO MAKE IT A BYTE POINTER AND ADD
; TO THE BEGINING ADDRESS OF PRELOAD.
;------------------------------------------------------------
GCALC: LDA GBEGIN+GGLOB+1 ; MAKE IT A BYTE POINTER WITH A * 2
ASL A
STA GLOBAL+LO
LDA GBEGIN+GGLOB
ROL A
CLC ; I THINK THE CARRY WOULD BE CLEAR ANYWAY
ADC GCODE
STA GLOBAL+HI
;***
; G-VAR #16 = # BLOCKSETS IN I-FILE
LDY #IBLKS ; GET # BLOCKSETS IN I-FILE
LDA (ICODE),Y
STA NBLOKS ; SAVE HERE
STA VALUE+LO ; MSB IS ALREADY CLEARED
LDA #16
JSR PUTVLG
; G-VAR #18 = # ICONS IN I-FILE
LDY #IICONS ; GET # ICONS IN I-FILE
LDA (ICODE),Y ; FROM THE I-FILE HEADER
STA NICONS ; SAVE HERE
STA VALUE+LO ; MSB ALREADY CLEARED
LDA #18
JSR PUTVLG
; [BTAB] = ABSOLUTE BLOCKSET TABLE ADDR
LDA ICODE+HI ; BLOCKSET TABLE BEGINS
STA BTAB+HI ; 8 BYTES AFTER THE START
LDA #8 ; OF THE I-FILE
STA BTAB+LO
; G-VAR #17 = V-WORD OF BLOCKSET TABLE
;***
LSR A ; /2 FOR 4-WORD OFFSET
;***
STA VALUE+LO ; SAME 8-BYTE OFFSET AS [BTAB]
LDA ISTART ; 1ST VIRTUAL PAGE # OF I-FILE
STA VALUE+HI
LDA #17
JSR PUTVLG
; G-VAR #19 = VIRTUAL WORD ADDRESS OF ICON TABLE
LDA NBLOKS ; GET # BLOCKS IN I-FILE
; ASL A ; WORD-ALIGN IT
; ROL MTEMP+HI ; TO GET SIZE OF BLOCKSET TABLE
; STA MTEMP+LO ; SAVE LSB OF SIZE
CLC ; ADD THE V-WORD ADDR OF THE B-TABLE
ADC VALUE+LO ; TO GET V-WORD ADDR OF I-TABLE
STA VALUE+LO ; INTO [VALUE]
; LDA MTEMP+HI
;***
LDA #00
;***
ADC VALUE+HI
STA VALUE+HI
LDA #19
JSR PUTVLG
; PREPARE FOR TABLE PATCHING
;***
LDA NBLOKS ; * 2 FOR LENGTH IN BYTES INSTED OF WORDS
ASL A
STA MTEMP+LO
ROL MTEMP+HI
;***
LDA BTAB+LO ; MAKE [I] POINT TO
STA I+LO ; START OF B-TABLE
CLC ; WHILE WE'RE AT IT,
ADC MTEMP+LO ; ADD SIZE OF B-TABLE
STA ITAB+LO ; TO GET ABS START ADDR OF I-TABLE
STA J+LO ; INTO [ITAB] AND [J]
LDA BTAB+HI ; DON'T FORGET MSBS!
STA I+HI
ADC MTEMP+HI
STA ITAB+HI
STA J+HI
; PATCH THE BLOCKSET TABLE
;***
;SHOULD WORK AS IS
;***
LDA NBLOKS ; GET # BLOCKSETS
STA QSIGN ; SAVE HERE FOR INDEXING
LDY #0 ; [I] HAS START OF B-TABLE
PATB: LDA (I),Y ; GET MSB OF A B-POINTER
CLC
ADC ISTART ; ADD ITS VIRTUAL OFFSET
STA (I),Y
INY ; NO NEED TO TOUCH LSB
INY ; SO SKIP OVER IT
BNE PATB1 ; CONTINUE UNTIL PAGE BOUNDARY HIT
INC I+HI ; IF HIT, POINT TO NEXT PAGE
PATB1: DEC QSIGN ; DECREMENT # BLOCKSETS
BNE PATB ; KEEP PATCHING TILL NONE LEFT
; PATCH THE ICON TABLE
LDA NICONS ; GET # ICONS
STA QSIGN ; FOR INDEXING
LDY #0 ; [J] HAS START OF I-TABLE
PATI: LDA (J),Y ; GET MSB OF I-POINTER
CLC
ADC ISTART ; ADD ITS VIRTUAL OFFSET
STA (J),Y
INY ; SKIP OVER LSB
INY
BNE PATI1
INC J+HI
PATI1: DEC QSIGN ; DECREMENT # ICONS
BNE PATI ; KEEP PATCHING TILL NONE LEFT
; INIT THE VIRTUAL MEMORY MAP
LDX #0 ; 1ST VIRTUAL PAGE
LDY GCODE ; 1ST ABSOLUTE PAGE OF G-PRELOAD
MINIT0: TYA
STA MEMMAP,X
INY ; NEXT ABSOLUTE PAGE
;***
INY ; SKIP 2 RAM PAGES FOR EVERY VIRTUAL PAGE
;***
INX ; NEXT VIRTUAL PAGE
CPX GPURE ; END OF PRELOAD?
BCC MINIT0 ; NO, KEEP FILLING
LDX ISTART ; 1ST VIRTUAL PAGE OF I-CODE
LDY ICODE+HI ; 1ST ABSOLUTE PAGE OF I-PRELOAD
MINIT1: TYA
STA MEMMAP,X
INY ; NEXT ABSOLUTE PAGE
;***
INY ; SKIP 2 RAM FOR EVERY 1 VIRTUAL
;***
INX ; NEXT VIRTUAL PAGE
CPX IPURE ; END OF I-PRELOAD?
BCC MINIT1
; ESTABLISH START ADDRESS OF G-PROGRAM
LDA GBEGIN+GSTART ; MSB
STA GPCH
LDA GBEGIN+GSTART+1 ; LSB
STA GPCL
;***
LDA #$01 ; START OF GAME IS ALWAYS ON THE ODD BYTE
STA GPC0 ; OF THE [GSTART] WORD
LDA #$00
STA GPCFLG
;***
; FALL THROUGH TO MAIN LOOP ...
END

131
atari/warm.src Normal file
View File

@@ -0,0 +1,131 @@
PAGE
SBTTL "--- WARMSTART ROUTINE ---"
; -------------
; ZIP WARMSTART
; -------------
WARM1: LDA #0 ; CLEAR ALL Z-PAGE VARIABLES
LDX #ZEROPG
ST0: STA 0,X
INX
; CPX #ZPGTOP ; NOT NEEDED FOR ATARI
BNE ST0
; INIT THE PAGING TABLE
TAX ; = 0
LDA #$FF
ST1: STA PTABL,X
STA PTABH,X
INX
BNE ST1
; CLEAR THE TIMESTAMP MAP
TXA ; = 0
ST2: STA LRUMAP,X
INX
BNE ST2
INC ZSP ; INIT Z-STACK POINTERS
INC OLDZSP ; TO "1"
INC STAMP ; INIT TIMESTAMP
; GRAB THE FIRST BLOCK OF PRELOAD
LDA #HIGH ZBEGIN ; MSB OF PRELOAD START ADDRESS
STA ZCODE ; FREEZE IT HERE
STA DBUFF+HI ; LSB IS ALWAYS ZERO
DEC ZPURE ; (ATARI ONLY) FORCE FETCH FROM PRELOAD
JSR GETDSK ; [DBLOCK] SET TO Z-BLOCK 0
; EXTRACT GAME DATA FROM Z-CODE HEADER
LDX ZBEGIN+ZENDLD ; MSB OF ENDLOAD POINTER
INX ; ADD 1 TO GET
STX ZPURE ; 1ST "PURE" PAGE OF Z-CODE
TXA ; ADD START PAGE OF PRELOAD
CLC ; TO CALC ABSOLUTE START ADDRESS
ADC ZCODE ; OF PAGING SPACE
STA PAGE0
JSR MEMTOP ; RETURNS TOP RAM PAGE IN [A]
SEC
SBC PAGE0 ; SUBTRACT ADDRESS OF PAGING SPACE
BEQ NORAM
BCS SETNP ; ERROR IF NOT ENOUGH RAM
; *** ERROR #0 -- INSUFFICIENT RAM ***
NORAM: LDA #0
JMP ZERROR
SETNP: STA PMAX ; SET # SWAPPING PAGES
LDA ZBEGIN+ZMODE
ORA #%00100000 ; ENABLE SPLIT-SCREEN
STA ZBEGIN+ZMODE
AND #%00000010 ; ISOLATE STATUS-FORMAT BIT
STA TIMEFL ; 0=SCORE, NZ=TIME
LDA ZBEGIN+ZGLOBA ; GET MSB OF GLOBAL TABLE ADDR
CLC ; CONVERT TO
ADC ZCODE ; ABSOLUTE ADDRESS
STA GLOBAL+HI
LDA ZBEGIN+ZGLOBA+1 ; LSB NEEDN'T CHANGE
STA GLOBAL+LO
LDA ZBEGIN+ZFWORD ; DO SAME FOR FWORDS TABLE
CLC
ADC ZCODE
STA FWORDS+HI
LDA ZBEGIN+ZFWORD+1 ; NO CHANGE FOR LSB
STA FWORDS+LO
LDA ZBEGIN+ZVOCAB ; NOW DO VOCABULARY TABLE
CLC
ADC ZCODE
STA VOCAB+HI
LDA ZBEGIN+ZVOCAB+1 ; LSB SAME
STA VOCAB+LO
LDA ZBEGIN+ZOBJEC ; NOT TO MENTION
CLC ; THE OBJECT TABLE
ADC ZCODE
STA OBJTAB+HI
LDA ZBEGIN+ZOBJEC+1 ; LSB SAME
STA OBJTAB+LO
; FETCH THE REST OF THE PRELOAD
LDPRE: LDA DBLOCK+LO ; CHECK CURRENT BLOCK #
CMP ZPURE ; LOADED LAST PRELOAD PAGE YET?
BCS WARMEX ; YES, TIME TO PLAY!
JSR GETDSK ; ELSE GRAB NEXT Z-BLOCK
JMP LDPRE
WARMEX: LDA ZBEGIN+ZGO ; GET START ADDRESS OF Z-CODE
STA ZPCM ; MSB
LDA ZBEGIN+ZGO+1 ; AND LSB
STA ZPCL ; HIGH BIT ALREADY ZEROED
LDA #21
STA LMAX ; PREVENT WEIRDNESS
JSR SIDE2 ; REQUEST SIDE 2 OF DISK
JSR CLS ; CLEAR SCREEN
LDA #$FF
STA SCRIPT ; ENABLE SCRIPTING
LDA ZBEGIN+ZSCRIP+1 ; SET SCRIPT FLAG
ORA SFLAG ; TO PREVIOUS SETTING
STA ZBEGIN+ZSCRIP+1 ; (BM 5/14/85)
; ... AND FALL INTO MAIN LOOP
END

490
atari/zdos.src Normal file
View File

@@ -0,0 +1,490 @@
PAGE
SBTTL "--- Z-DOS: ATARI ---"
; -----------------------------
; SET UP SAVE & RESTORE SCREENS
; -----------------------------
SAVRES: JSR ZCRLF ; CLEAR THE LINE BUFFER
JSR CLS ; AND THE SCREEN
LDA #0
STA SCRIPT ; DISABLE SCRIPTING
STA COLCRS+LO ; HOME CURSOR
STA ROWCRS
RTS
; -----------------
; DISPLAY A DEFAULT
; -----------------
; ENTRY: DEFAULT (1-8) IN [A]
DEFAL: DB " (Default is "
DEFNUM: DB "*) >"
DEFALL EQU $-DEFAL
DODEF: CLC
ADC #'1' ; CONVERT TO ASCII 1-9
STA DEFNUM ; INSERT IN STRING
LDX #LOW DEFAL
LDA #HIGH DEFAL
LDY #DEFALL
JMP DLINE ; PRINT THE STRING
; -----------------------------
; GET SAVE & RESTORE PARAMETERS
; -----------------------------
POSIT: DB EOL
DB "Position 1-5"
POSITL EQU $-POSIT
WDRIV: DB EOL
DB "Drive 1 or 2"
WDRIVL EQU $-WDRIV
MIND: DB EOL
DB EOL
DB "Position "
MPOS: DB "*; Drive #"
MDRI: DB "*."
DB EOL
DB "Are you sure? (Y or N) >"
MINDL EQU $-MIND
INSM: DB EOL
DB "Insert SAVE disk into Drive #"
SAVDRI: DB "*."
INSML EQU $-INSM
YES: DB "YES"
DB EOL
YESL EQU $-YES
NO: DB "NO"
DB EOL
NOL EQU $-NO
PARAMS: LDX #LOW POSIT
LDA #HIGH POSIT
LDY #POSITL
JSR DLINE ; "POSITION (1-5)"
; GET GAME SAVE POSITION
LDA GPOSIT ; SHOW THE CURRENT
JSR DODEF ; DEFAULT POSITION
GETPOS: JSR GETKEY ; WAIT FOR A KEY
CMP #EOL ; IF [RETURN],
BEQ POSSET ; USE DEFAULT
SEC
SBC #'1' ; ELSE CONVERT ASCII TO BINARY
CMP #5 ; IF BELOW "5"
BCC SETPOS ; MAKE IT THE NEW DEFAULT
JSR BOOP ; ELSE RAZZ
JMP GETPOS ; AND TRY AGAIN
POSSET: LDA GPOSIT ; USE DEFAULT
SETPOS: STA TPOSIT ; USE KEYPRESS
CLC
ADC #'1' ; CONVERT TO ASCII "1"-"5"
STA MPOS ; STORE IN TEMP STRING
STA SVPOS
STA RSPOS
JSR CHAR ; AND DISPLAY IT
; GET DRIVE ID
LDX #LOW WDRIV
LDA #HIGH WDRIV
LDY #WDRIVL
JSR DLINE ; "DRIVE 1 OR 2"
LDA GDRIVE ; SHOW DEFAULT
JSR DODEF
GETDRV: JSR GETKEY ; GET A KEYPRESS
CMP #EOL ; IF [RETURN],
BEQ DRVSET ; USE DEFAULT
SEC
SBC #'1' ; CONVERT TO BINARY 0 OR 1
CMP #2 ; IF WITHIN RANGE,
BCC SETDRV ; SET NEW DEFAULT
JSR BOOP
JMP GETDRV ; ELSE TRY AGAIN
DRVSET: LDA GDRIVE ; USE DEFAULT
SETDRV: STA TDRIVE ; USE [A]
CLC
ADC #'1' ; CONVERT TO ASCII 1 OR 2
STA SAVDRI ; STORE IN DRIVE STRING
STA MDRI ; AND IN TEMP STRING
JSR CHAR ; AND SHOW NEW SETTING
LDX #LOW MIND ; SHOW TEMPORARY SETTINGS
LDA #HIGH MIND
LDY #MINDL
JSR DLINE
; VALIDATE RESPONSES
LDA #$FF
STA CH
GETYES: JSR GETKEY
CMP #'y' ; IF REPLY IS "Y"
BEQ ALLSET ; ACCEPT RESPONSES
CMP #'Y'
BEQ ALLSET
CMP #EOL ; EOL IS ALSO ACCEPTABLE
BEQ ALLSET
CMP #'n' ; IF REPLY IS "N"
BEQ NOTSAT ; RESTATE PARAMETERS
CMP #'N'
BEQ NOTSAT
JSR BOOP ; ELSE BOOP
JMP GETYES ; INSIST ON Y OR N
NOTSAT: LDX #LOW NO
LDA #HIGH NO
LDY #NOL
JSR DLINE ; PRINT "NO"/EOL
JMP PARAMS ; AND TRY AGAIN
ALLSET: LDX #LOW YES
LDA #HIGH YES
LDY #YESL
JSR DLINE ; PRINT "YES"/EOL
LDA TDRIVE ; MAKE THE TEMPORARY DRIVE
STA GDRIVE ; THE DEFAULT DRIVE
STA DRIVE ; AND SET [DRIVE] ACCORDINGLY
INC DRIVE ; 1-ALIGN THE DRIVE ID
LDX TPOSIT ; MAKE THE TEMP POSITION
STX GPOSIT ; THE DEFAULT POSITION
; CALC TRACK & SECTOR OF GAME POSITION
LDA OFFLOS,X ; INDEX INTO THE OFFSET TABLES
STA SECTOR+LO ; SET [SECTOR] = 1ST SECTOR
LDA OFFHIS,X ; IN REQUESTED SAVE POSITION
STA SECTOR+HI
LDX #LOW INSM
LDA #HIGH INSM
LDY #INSML
JSR DLINE ; "INSERT SAVE DISK IN DRIVE X."
; FALL THROUGH ...
; ---------------------
; "PRESS RETURN" PROMPT
; ---------------------
RETURN: JSR ZCRLF
LDX #LOW RTN
LDA #HIGH RTN
LDY #RTNL
JSR DLINE ; SHOW PROMPT
JSR ZCRLF
LDA #'>'
JSR CHAR
; ENTRY FOR QUIT/RESTART
GETRET: LDA #$FF
STA CH
GTRT0: JSR GETKEY ; WAIT FOR [RETURN]
CMP #EOL
BEQ GTRT1
JSR BOOP ; ACCEPT NO
JMP GTRT0 ; SUBSTITUTES!
GTRT1: RTS
RTN: DB "Press [RETURN] to continue."
RTNL EQU $-RTN
; --------------------
; PROMPT FOR GAME DISK
; --------------------
GAME: DB "Insert Side "
DSIDE: DB "2 of the STORY disk into"
GAMEL EQU $-GAME
GAME2: DB "Drive #1."
GAME2L EQU $-GAME2
SIDE1: LDA #'1' ; ASK FOR SIDE 1
BNE DOSIDE
SIDE2: LDA #'2' ; ASK FOR SIDE 2
DOSIDE: STA DSIDE
LDA #1 ; MAKE SURE WE'RE ON
STA DRIVE ; THE BOOT DRIVE
JSR ZCRLF
LDX #LOW GAME
LDA #HIGH GAME
LDY #GAMEL
JSR DLINE ; "INSERT STORY DISK"
JSR ZCRLF
LDX #LOW GAME2
LDA #HIGH GAME2
LDY #GAME2L
JSR DLINE ; "DRIVE #1"
JSR RETURN ; "PRESS [RETURN] TO CONTINUE:"
LDA #$FF ; ENABLE
STA SCRIPT ; SCRIPTING
RTS
; -------------------------
; SET UP PHONEY STATUS LINE
; -------------------------
; ENTRY: TEXT SET UP FOR "DLINE"
SROOM: JSR DLINE ; PRINT LINE IN [X/Y/A]
LDX #39 ; INVERT & BLACKEN TOP LINE
SRLP: LDA SCREEN,X
ORA #%10000000
STA SCREEN,X
DEX
BPL SRLP
RTS
; ---------
; SAVE GAME
; ---------
SAV: DB "Save Position"
DB EOL
SAVL EQU $-SAV
SVING: DB EOL
DB EOL
DB "Saving position "
SVPOS: DB "* ..."
DB EOL
SVINGL EQU $-SVING
ZSAVE: JSR SAVRES ; SET UP SCREEN
LDX #LOW SAV
LDA #HIGH SAV
LDY #SAVL
JSR SROOM ; "SAVE POSITION"
JSR PARAMS ; GET PARAMETERS
LDX #LOW SVING
LDA #HIGH SVING
LDY #SVINGL
JSR DLINE ; "SAVING POSITION X ..."
; SAVE GAME PARAMETERS IN [BUFSAV]
LDA ZBEGIN+ZID ; MOVE GAME ID
STA BUFSAV+0 ; INTO 1ST 2 BYTES
LDA ZBEGIN+ZID+1 ; OF THE AUX LINE BUFFER
STA BUFSAV+1
LDA ZSP ; MOVE [ZSP]
STA BUFSAV+2 ; TO 3RD BYTE
LDA OLDZSP ; MOVE [OLDZSP]
STA BUFSAV+3 ; TO 4TH
LDX #2 ; MOVE CONTENTS OF [ZPC]
ZPCSAV: LDA ZPC,X ; TO BYTES 5-7
STA BUFSAV+4,X ; OF [BUFSAV]
DEX
BPL ZPCSAV
; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK
LDA #HIGH LOCALS
STA DBUFF+HI ; POINT TO THE PAGE
JSR PUTDSK ; AND WRITE IT OUT
BCC WSTACK ; IF SUCCEEDED, WRITE STACK
BADSAV: JSR SIDE2 ; ELSE REQUEST STORY DISK
JSR CLS
JMP PREDF ; AND FAIL
; WRITE CONTENTS OF Z-STACK TO DISK
WSTACK: LDA #HIGH ZSTAKL ; POINT TO 1ST PAGE
STA DBUFF+HI
JSR PUTDSK ; WRITE 1ST AND
BCS BADSAV
JSR PUTDSK ; 2ND PAGE OF Z-STACK
BCS BADSAV
; WRITE ENTIRE GAME PRELOAD TO DISK
LDA ZCODE ; POINT TO 1ST PAGE
STA DBUFF+HI ; OF PRELOAD
LDX ZBEGIN+ZPURBT ; GET # IMPURE PAGES
INX ; USE FOR INDEXING
STX I+LO
LSAVE: JSR PUTDSK
BCS BADSAV
DEC I+LO
BNE LSAVE
JSR SIDE2 ; PROMPT FOR GAME DISK
JSR CLS
JMP PREDS ; ELSE PREDICATE SUCCEEDS
; ------------
; RESTORE GAME
; ------------
RES: DB "Restore Position"
DB EOL
RESL EQU $-RES
RSING: DB EOL
DB EOL
DB "Restoring position "
RSPOS: DB "* ..."
DB EOL
RSINGL EQU $-RSING
ZREST: JSR SAVRES
LDX #LOW RES
LDA #HIGH RES
LDY #RESL
JSR SROOM ; "RESTORE POSITION"
JSR PARAMS ; GET PARAMETERS
LDX #LOW RSING
LDA #HIGH RSING
LDY #RSINGL
JSR DLINE ; "RESTORING POSITION X ..."
; SAVE LOCALS IN CASE OF ERROR
LDX #31
LOCSAV: LDA LOCALS,X ; COPY ALL LOCALS
STA $0100,X ; TO BOTTOM OF MACHINE STACK
DEX
BPL LOCSAV
LDA #HIGH LOCALS
STA DBUFF+HI
JSR RDISK ; RETRIEVE 1ST BLOCK OF PRELOAD
BCS WRONG ; BAD DISK READ IF CARRY CLEAR
LDA BUFSAV+0 ; DOES 1ST BYTE OF SAVED GAME ID
CMP ZBEGIN+ZID ; MATCH THE CURRENT ID?
BNE WRONG ; WRONG DISK IF NOT
LDA BUFSAV+1 ; WHAT ABOUT THE 2ND BYTE?
CMP ZBEGIN+ZID+1
BEQ RIGHT ; CONTINUE IF BOTH BYTES MATCH
; HANDLE RESTORE ERROR
WRONG: LDX #31 ; RESTORE ALL SAVED LOCALS
WR0: LDA $0100,X
STA LOCALS,X
DEX
BPL WR0
JSR SIDE2 ; PROMPT FOR GAME DISK
JSR CLS
JMP PREDF ; PREDICATE FAILS
; CONTINUE RESTORE
RIGHT: LDA ZBEGIN+ZSCRIP ; SAVE BOTH FLAG BYTES
STA I+LO
LDA ZBEGIN+ZSCRIP+1
STA I+HI
LDA #HIGH ZSTAKL ; RETRIEVE OLD CONTENTS OF
STA DBUFF+HI ; Z-STACK
JSR RDISK ; GET 1ST BLOCK OF Z-STACK
BCS WRONG
JSR RDISK ; AND 2ND BLOCK
BCS WRONG
LDA ZCODE
STA DBUFF+HI
JSR RDISK ; GET 1ST BLOCK OF PRELOAD
BCS WRONG
LDA I+LO ; RESTORE THE STATE
STA ZBEGIN+ZSCRIP ; OF THE FLAG WORD
LDA I+HI
STA ZBEGIN+ZSCRIP+1
LDA ZBEGIN+ZPURBT ; GET # PAGES TO LOAD
STA I+LO
LREST: JSR RDISK ; FETCH THE REMAINDER
BCS WRONG
DEC I+LO ; OF THE PRELOAD
BNE LREST
; RESTORE THE STATE OF THE SAVED GAME
LDA BUFSAV+2 ; RESTORE THE [ZSP]
STA ZSP
LDA BUFSAV+3 ; AND THE [OLDZSP]
STA OLDZSP
LDX #2 ; RESTORE THE [ZPC]
RESZPC: LDA BUFSAV+4,X
STA ZPC,X
DEX
BPL RESZPC
LDA #0
STA ZPCFLG ; INVALIDATE [ZPC]
JSR SIDE2 ; PROMPT FOR GAME DISK
JSR CLS
JMP PREDS ; PREDICATE SUCCEEDS
; --------------------------
; SAVE/RESTORE OFFSET TABLES
; --------------------------
; 144 SECTORS (18K) PER SAVE POSITION
OFFLOS: DB LOW 1
DB LOW 145
DB LOW 289
DB LOW 433
DB LOW 577
OFFHIS: DB HIGH 1
DB HIGH 145
DB HIGH 289
DB HIGH 433
DB HIGH 577
END

75
atari/zip.src Normal file
View File

@@ -0,0 +1,75 @@
TITLE "ZIP/6502 INFOCOM, INC. --- EQUATES"
; --------------------------
; ZIP/6502 2.0
; Z-CODE INTERPRETER PROGRAM
; FOR ATARI 400/800/1200/XL
; --------------------------
; INFOCOM, INC.
; 55 WHEELER STREET
; CAMBRIDGE, MA 02136
; COMPANY PRIVATE -- NOT FOR DISTRIBUTION
ZEROPG EQU $80 ; 1ST FREE Z-PAGE LOCATION
DEBUG EQU 0 ; ASSEMBLY FLAG FOR DEBUGGER
; -----------
; ERROR CODES
; -----------
; 00 -- INSUFFICIENT RAM
; 01 -- ILLEGAL X-OP
; 02 -- ILLEGAL 0-OP
; 03 -- ILLEGAL 1-OP
; 04 -- ILLEGAL 2-OP
; 05 -- Z-STACK UNDERFLOW
; 06 -- Z-STACK OVERFLOW
; 07 -- ILLEGAL PROPERTY LENGTH (GETP)
; 08 -- DIVISION BY ZERO
; 09 -- ILLEGAL ARGUMENT COUNT (EQUAL?)
; 10 -- ILLEGAL PROPERTY ID (PUTP)
; 11 -- ILLEGAL PROPERTY LENGTH (PUTP)
; 12 -- DISK ADDRESS OUT OF RANGE
; 13 -- PARSER OVERFLOW
; 14 -- DRIVE ACCESS
INCLUD EQ.ASM
TITLE "ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT INIT"
INCLUD HARDEQ.ASM
INCLUD COLD.ASM
TITLE "ZIP/6502 INFOCOM, INC. --- INIT & MAINLINE"
INCLUD WARM.ASM
INCLUD MAIN.ASM
INCLUD SUBS.ASM
INCLUD DISPATCH.ASM
TITLE "ZIP/6502 INFOCOM, INC. --- OPCODE EXECUTORS"
INCLUD OPS0.ASM
INCLUD OPS1.ASM
INCLUD OPS2.ASM
INCLUD OPSX.ASM
INCLUD READ.ASM
TITLE "ZIP/6502 INFOCOM, INC. --- OP SUPPORT & MEMORY MANAGEMENT"
INCLUD PAGING.ASM
INCLUD ZSTRING.ASM
INCLUD OBJECTS.ASM
TITLE "ZIP/6502 INFOCOM, INC. --- MACHINE DEPENDENT"
INCLUD IO.ASM
INCLUD MACHINE.ASM
INCLUD ZDOS.ASM
INCLUD DISK.ASM
IF DEBUG
INCLUD BUGGER.ASM
ENDIF
TITLE "ZIP/6502 INFOCOM, INC."
END

437
atari/zstring.src Normal file
View File

@@ -0,0 +1,437 @@
PAGE
SBTTL "--- Z-STRING HANDLERS ---"
; -----------------------
; POINT TO ZSTRING IN [I]
; -----------------------
SETSTR: LDA I+LO ; WORD-ALIGN THE ADDRESS
ASL A
STA MPCL
LDA I+HI
ROL A
STA MPCM
LDA #0
STA MPCFLG ; [MPC] IS CHANGING!
ROL A
STA MPCH
ZSTEX: RTS
; -----------------------
; PRINT Z-STRING AT [MPC]
; -----------------------
PZSTR: LDX #0
STX PSET ; ASSUME PERMANENT CHARSET
STX ZFLAG ; CLEAR BYTE FLAG
DEX ; = $FF
STX TSET ; NO TEMPSET ACTIVE
PZTOP: JSR GETZCH ; GET A Z-CHAR
BCS ZSTEX ; END OF STRING IF CARRY IS SET
STA ZCHAR ; ELSE SAVE CHAR HERE
TAX ; SET FLAGS
BEQ BLANK ; PRINT SPACE IF CHAR = 0
CMP #4 ; IS THIS AN F-WORD?
BCC DOFREQ ; APPARENTLY SO
CMP #6 ; PERHAPS A SHIFT CODE?
BCC NEWSET ; YES, CHANGE CHARSETS
JSR GETSET ; ELSE GET CHARSET
TAX ; SET FLAGS
BNE SET1 ; SKIP IF NOT CHARSET #0
; PRINT A LOWER-CASE CHAR (CHARSET #0)
LDA #$61-6 ; ASCII "a" MINUS Z-OFFSET
TOASC: CLC
ADC ZCHAR ; ADD Z-CHAR INDEX
SHOVE: JSR COUT ; SHOW THE CHAR
JMP PZTOP ; AND GRAB NEXT CHAR
; PRINT AN UPPER-CASE CHAR (CHARSET #1)
SET1: CMP #1 ; MAKE SURE IT'S SET #1
BNE SET2 ; ELSE MUST BE SET #2
LDA #$41-6 ; ASCII "A" MINUS Z-OFFSET
BNE TOASC ; SAME AS SET #0
; PRINT FROM CHARSET #2
SET2: LDA ZCHAR ; RETRIEVE THE Z-CHAR
SEC
SBC #6 ; ZERO-ALIGN IT
BEQ DIRECT ; IF ZERO, IT'S A "DIRECT" ASCII
TAX ; OTHERWISE USE CODE AS AN INDEX
LDA CHRTBL,X ; INTO THE CHARSET TABLE
JMP SHOVE ; AND PRINT THE CHAR
; DECODE A "DIRECT" ASCII CHAR
DIRECT: JSR GETZCH ; FETCH NEXT Z-CHAR
ASL A
ASL A
ASL A
ASL A
ASL A ; SHIFT INTO POSITION
STA ZCHAR ; AND SAVE HERE
JSR GETZCH ; GRAB YET ANOTHER Z-CHAR
ORA ZCHAR ; SUPERIMPOSE THE 2ND BYTE
JMP SHOVE ; AND PRINT THE RESULT
; PRINT A SPACE
BLANK: LDA #SPACE ; ASCII SPACE CHAR
BNE SHOVE
; CHANGE CHARSET
NEWSET: SEC ; CONVERT THE SHIFT CODE
SBC #3 ; TO 1 OR 2
TAY
JSR GETSET ; IS MODE TEMPORARY?
BNE TOPERM ; YES, DO A PERMSHIFT
STY TSET ; ELSE JUST A TEMPSHIFT
JMP PZTOP ; AND CONTINUE
TOPERM: STY PSET ; SET PERM CHARSET
CMP PSET ; SAME AS BEFORE?
BEQ PZTOP ; YES, CONTINUE
LDA #0
STA PSET ; ELSE RESET CHARSET
BEQ PZTOP ; BEFORE LOOPING BACK
; PRINT AN F-WORD
DOFREQ: SEC
SBC #1 ; ZERO-ALIGN THE CODE
ASL A ; AND MULTIPLY TIMES 64
ASL A ; TO OBTAIN THE SEGMENT OFFSET
ASL A ; INTO THE F-WORDS TABLE
ASL A
ASL A
ASL A
STA OFFSET ; SAVE OFFSET FOR LATER
JSR GETZCH ; NOW GET THE F-WORD POINTER
ASL A ; WORD-ALIGN IT
CLC ; AND
ADC OFFSET ; ADD THE SEGMENT OFFSET
TAY ; TO GET THE OFFSET OF THE F-WORD
LDA (FWORDS),Y ; FROM THE START OF THE F-WORDS TABLE
STA I+HI ; SAVE MSB OF F-WORD ADDRESS
INY
LDA (FWORDS),Y ; ALSO SAVE LSB
STA I+LO ; Z-ADDRESS OF F-WORD IS IN [I]
; SAVE THE STATE OF CURRENT Z-STRING
LDA MPCH
PHA
LDA MPCM
PHA
LDA MPCL
PHA
LDA PSET
PHA
LDA ZFLAG
PHA
LDA ZWORD+HI
PHA
LDA ZWORD+LO
PHA
JSR SETSTR ; PRINT THE Z-STRING
JSR PZSTR ; IN [I]
; RESTORE OLD Z-STRING
PLA
STA ZWORD+LO
PLA
STA ZWORD+HI
PLA
STA ZFLAG
PLA
STA PSET
PLA
STA MPCL
PLA
STA MPCM
PLA
STA MPCH
LDX #$FF
STX TSET ; DISABLE TEMP CHARSET
INX ; = 0
STX MPCFLG ; [MPC] HAS CHANGED
JMP PZTOP ; CONTINUE INNOCENTLY
; ----------------------
; RETURN CURRENT CHARSET
; ----------------------
GETSET: LDA TSET
BPL GS
LDA PSET
RTS
GS: LDY #$FF
STY TSET
RTS
; -----------------
; FETCH NEXT Z-CHAR
; -----------------
GETZCH: LDA ZFLAG ; WHICH BYTE IS THIS?
BPL GTZ0 ; $FF = LAST
SEC ; SET CARRY TO INDICATE
RTS ; NO MORE CHARS
GTZ0: BNE GETZ1 ; NOT FIRST CHAR, EITHER
; GET A Z-WORD INTO [ZWORD], RETURN 1ST CHAR IN TRIPLET
INC ZFLAG ; UPDATE CHAR COUNT
JSR GETBYT ; GET TRIPLET AT [MPC]
STA ZWORD+HI ; INTO [ZWORD]
JSR GETBYT
STA ZWORD+LO
LDA ZWORD+HI
LSR A
LSR A ; SHIFT 1ST CHAR INTO PLACE
JMP GTEXIT ; AND RETURN IT
GETZ1: SEC
SBC #1
BNE GETZ2 ; LAST CHAR IN TRIPLET IF ZERO
LDA #2 ; ELSE
STA ZFLAG ; RESET CHAR INDEX
LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET
STA I+LO ; MOVE HERE FOR SHIFTING
LDA ZWORD+HI ; GET TOP HALF
ASL I+LO ; SHIFT THE TOP 3 BITS OF LOWER HALF
ROL A ; INTO THE BOTTOM OF THE TOP HALF
ASL I+LO
ROL A
ASL I+LO
ROL A
JMP GTEXIT
GETZ2: LDA #0 ; SET FLAG TO INDICATE
STA ZFLAG ; END OF TRIPLET
LDA ZWORD+HI ; TEST TOP HALF OF TRIPLET
BPL GETZ3 ; CONTINUE IF NOT END OF STRING
LDA #$FF ; ELSE
STA ZFLAG ; INDICATE LAST TRIPLET IN STRING
GETZ3: LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET
GTEXIT: AND #%00011111 ; MASK OUT GARBAGE BITS
CLC
RTS
; ---------------------------------
; CONVERT [IN] TO Z-STRING IN [OUT]
; ---------------------------------
CONZST: LDA #$05 ; FILL OUTPUT BUFFER
TAX ; WITH PAD CHARS ($05)
CZSL: STA OUT,X
DEX
BPL CZSL
LDA #6 ; INIT
STA CONCNT ; CHAR COUNT
LDA #0 ; CLEAR
STA CONIN ; SOURCE AND
STA CONOUT ; OUTPUT INDEXES
CONTOP: LDX CONIN ; FETCH SOURCE INDEX
INC CONIN ; AND UPDATE
LDA IN,X ; GRAB AN ASCII CHAR
STA ZCHAR ; SAVE IT HERE
BNE NEXTZ ; CONTINUE IF CHAR WAS NZ
LDA #5 ; ELSE SHIP OUT
BNE CSHIP ; A PAD CHAR
NEXTZ: LDA ZCHAR
JSR SAYSET ; WHICH CHARSET TO USE?
BEQ CSET0 ; LOWER-CASE IF ZERO
CLC ; ELSE DO A TEMP-SHIFT
ADC #3 ; 4 = CHARSET 1, 5 = CHARSET 2
LDX CONOUT ; FETCH OUTPUT INDEX
STA OUT,X ; SEND THE SHIFT CHAR
INC CONOUT ; UPDATE INDEX
DEC CONCNT ; AND CHAR COUNT
BNE CTEST ; IF OUT OF CHARS
JMP ZCRUSH ; CRUSH 'EM!
CTEST: LDA ZCHAR ; TEST CHAR AGAIN
JSR SAYSET
CMP #2
BEQ CSET2 ; CHARSET #2
; HANDLE CHARSET #1 (UPPER CASE ALPHA)
LDA ZCHAR
SEC
SBC #$41-6 ; CONVERT TO Z-CHAR
BPL CSHIP ; AND SEND TO OUTPUT
; HANDLE CHARSET #0 (LOWER CASE ALPHA)
CSET0: LDA ZCHAR
SEC
SBC #$61-6 ; CONVERT TO Z-CHAR
; SHIP Z-CHAR TO OUTPUT BUFFER
CSHIP: LDX CONOUT ; FETCH OUTPUT INDEX
STA OUT,X
INC CONOUT ; UPDATE INDEX
DEC CONCNT ; DONE 6 CHARS YET?
BNE CONTOP ; NO, LOOP BACK
JMP ZCRUSH ; ELSE CRUSH
; HANDLE CHARSET #2 (MISCELLANEOUS)
CSET2: LDA ZCHAR ; GRAB CHAR
JSR CTABLE ; IS IT IN CHARSET #3 TABLE?
BNE CSHIP ; YES, SEND IT TO OUTPUT
; SEND A "DIRECT" ASCII CHAR
LDA #6 ; ASCII ALERT!
LDX CONOUT
STA OUT,X
INC CONOUT ; UPDATE INDEX
DEC CONCNT ; AND CHAR COUNT
BEQ ZCRUSH ; BUFFER FULL!
; SEND 1ST HALF OF "DIRECT"
LDA ZCHAR
LSR A
LSR A
LSR A
LSR A
LSR A
AND #%00000011 ; MASK GARBAGE
LDX CONOUT
STA OUT,X
INC CONOUT
DEC CONCNT
BEQ ZCRUSH ; BUFFER FULL!
; SEND 2ND HALF OF "DIRECT"
LDA ZCHAR ; GET CHAR YET AGAIN
AND #%00011111 ; MASK JUNK
JMP CSHIP ; AND SHIP IT OUT
; ---------------------
; IS [A] IN CHARSET #3?
; ---------------------
; EXIT: [A] = CHAR CODE IF FOUND, Z-FLAG CLEARED
; Z-FLAG SET IF NOT FOUND
CTABLE: LDX #25
CNL: CMP CHRTBL,X
BEQ CNOK
DEX
BNE CNL
RTS ; Z-FLAG SET IF NO MATCH
CNOK: TXA ; CHAR CODE IS INDEX
CLC
ADC #6 ; PLUS 6
RTS
; -----------------------------
; RETURN CHARSET OF CHAR IN [A]
; -----------------------------
SAYSET: CMP #'a'
BCC SAY1
CMP #'z'+1
BCS SAY1
LDA #0 ; IT'S CHARSET #0
RTS
SAY1: CMP #'A'
BCC SAY2
CMP #'Z'+1
BCS SAY2
LDA #1 ; IT'S CHARSET #1
RTS
SAY2: LDA #2 ; IT'S CHARSET #2
RTS
; ----------------------
; CRUSH Z-CHARS IN [OUT]
; ----------------------
ZCRUSH: LDA OUT+1 ; GET 2ND Z-CHAR
ASL A ; SHIFT BITS INTO POSITION
ASL A
ASL A
ASL A
ROL OUT ; ALONG WITH 1ST Z-CHAR
ASL A
ROL OUT
ORA OUT+2 ; SUPERIMPOSE 3RD Z-CHAR
STA OUT+1
LDA OUT+4 ; GET 5TH Z-CHAR
ASL A ; SHIFT BITS
ASL A
ASL A
ASL A
ROL OUT+3 ; ALONG WITH 4TH Z-CHAR
ASL A
ROL OUT+3
ORA OUT+5 ; SUPERIMPOSE 6TH Z-CHAR
TAX ; SAVE HERE
LDA OUT+3 ; GRAB 4TH Z-CHAR
ORA #%10000000 ; SET HIGH BIT
STA OUT+2 ; MOVE CRUSHED Z-WORD
STX OUT+3 ; INTO PLACE
RTS
; -----------------------
; CHARSET #2 DECODE TABLE
; -----------------------
CHRTBL: DB 0 ; DUMMY BYTE FOR "DIRECT"
DB $0D ; EOL
DB "0123456789.,!?_#"
DB $27 ; SINGLE QUOTE
DB $22 ; DOUBLE QUOTE
DB "/\-:()"
END