; ------------------------ ; ONE FOR THE ROAD ; by Clayton Walnum ; ANALOG Computing # ; (C)1985 ANALOG Computing ; ------------------------ ; ; MACRO DEFINITIONS ; ----------------- ; ; POSITION MACRO ; -------------- ; SYNTAX: ; POSITION xpos,ypos ; .MACRO POSITION .IF %0<>2 .OR %1>39 .OR %2>23 .ERROR "POS parameters" .ELSE .IF %1=13 LDY #%2 JSR POSIT13 .ELSE LDX #%1 LDY #%2 JSR POSIT .ENDIF .ENDIF .ENDM ; ; PRINT MACRO ; ----------- ; SYNTAX: ; PRINT ; .MACRO PRINT .IF %0<>1 .ERROR "PRINTE parameters" .ELSE LDA # <%1 LDY # >%1 JSR EPRINT .ENDIF .ENDM ; ; TEXT MACRO ; ---------- ; SYNTAX: ; TEXT <"string"> ; .MACRO TEXT .IF %0<>1 .OR %1>127 .ERROR "TEXT parameters" .ELSE .BYTE %$1,EOL .ENDIF .ENDM ; ; SYSTEM EQUATES ; --------------- ; ; ZERO-PAGE ; --------- BOOT? = $09 ; OS boot flag POKMSK = $10 ; interrupt mask RTCLOK = $14 ; system clock LMARGN = $52 ; left margin RMARGN = $53 ; right margin ROWCRS = $54 ; cursor row COLCRS = $55 ; cursor column RAMTOP = $6A ; # pages of RAM FR0 = $D4 ; floating point register CIX = $F2 ; FP index register INBUFF = $F3 ; FP pointer ; ; PAGES 2-3 ; --------- VDSLST = $0200 ; DLI vector SRTIMR = $022B ; key repeat timer SDMCTL = $022F ; DMA control SDLSTL = $0230 ; D-list addr COLDST = $0244 ; coldstart flag GPRIOR = $026F ; PMG priority PCOLR0 = $02C0 ; player 0 color PCOLR1 = $02C1 ; player 1 color PCOLR2 = $02C2 ; player 2 color PCOLR3 = $02C3 ; player 3 color COLOR0 = $02C4 ; playfield 0 color COLOR1 = $02C5 ; playfield 1 color COLOR2 = $02C6 ; playfield 2 color COLOR4 = $02C8 ; background color CRSINH = $02F0 ; cursor inhibit CHBAS = $02F4 ; adr of char set CH = $02FC ; keypress register ICCOM = $0342 ; CIO command ICBADR = $0344 ; CIO addr ICBLEN = $0348 ; CIO length ICAUX1 = $034A ; AUX byte 1 ICAUX2 = $034B ; AUX byte 2 ; ; CTIA/GTIA ; --------- HPOSP0 = $D000 ; h-pos player 0 HPOSP1 = $D001 ; " " 1 HPOSP2 = $D002 ; " " 2 HPOSP3 = $D003 ; " " 3 SIZEP0 = $D004 ; width player 0 SIZEP1 = $D009 ; " " 1 SIZEP2 = $D00A ; " " 2 SIZEP3 = $D00B ; " " 3 GRAFP0 = $D00D ; graphics player 0 GRAFP1 = $D00E ; " " 1 GRAFP2 = $D00F ; " " 2 GRAFP3 = $D010 ; " " 3 COLPF2 = $D018 ; color register 2 CONSOL = $D01F ; console keys ; ; POKEY ; ----- AUDF1 = $D200 ; frequency channel 1 AUDC1 = $D201 ; vol/dist channel 1 AUDCTL = $D208 ; audio control RANDOM = $D20A ; random # generator IRQEN = $D20E ; interrupt enable ; ; ANTIC ; ----- DMACTL = $D400 ; DMA control WSYNC = $D40A ; wait for horz sync NMIEN = $D40E ; NMI enable ; ; FLOATING POINT ; -------------- FASC = $D8E6 ; FP-to-ATASCII IFP = $D9AA ; integer-to-FP ZFR0 = $DA44 ; clear FR0 ; ; OS ROUTINES ; ----------- CIOV = $E456 ; CIO entry SETVBV = $E45C ; set v-blank vector SYSVBV = $E45F ; OS VBI entry SIOINV = $E465 ; SIO init ; ; INTERNAL EQUATES ; ---------------- ; ; MEMORY ALLOCATION ; ----------------- INLINE = $0600 ; text input buffer GAMEDATA = $3AC0 ; working area EDLIST = $3C20 ; start of E: display list SCREEN = $3C40 ; start of screen RAM ; ; Game play database ; *= GAMEDATA ; EVENT *= *+2 ; event # PLACE *= *+1 ; location CABINET *= *+1 ; cabibet opened RAFTIN *= *+1 ; raft in the water INFLATE *= *+1 ; raft inflated? CHEST *= *+1 ; chest open? JUG *= *+1 ; jug open? ROBE *= *+1 ; wearing robe? SACRIF *= *+1 ; sacrifice performed? GOBLET *= *+1 ; goblet filled? SHELVES *= *+1 ; shelves moved? DRINK *= *+1 ; liquid consumed? PAPER *= *+1 ; paper inserted? PHOTO *= *+1 ; photo inserted? DPLACE *= *+1 ; location of dynamite OIL *= *+1 ; oil poured? LIT *= *+1 ; match lit? MATCNT *= *+1 ; # of matches CHECNT *= *+1 ; chest turn counter WALLET *= *+1 ROCKCNT *= *+1 ; hit rocks counter CORD *= *+1 ; cord pulled? RAFTFND *= *+1 ; raft found? DYNAFND *= *+1 ; dynamite found? SNAKE *= *+1 ; snake dead? LASSO *= *+1 ; got coconut? LITCNT *= *+1 ; match counter BLAST *= *+1 ; dynamite lit? HOLDINGS *= *+6 ; current inventory VECTORS *= *+132 ; current vector table OBJECTS *= *+132 ; current object table NTRANS *= *+38 ; current translation matrix ; ; MISCELLANEOUS ; ------------- EOL = $9B SPACE = $20 SETPNT = $CD OFFCNT = $CF NEWSET = $4400 ROMSET = $E000 ; ; ZERO-PAGE ; --------- *= $80 ; ; Cursor control ; CURSEN *= *+1 ; cursor on/off flag CSHAPE *= *+1 ; current cursor shape BLINK *= *+1 ; cursor blink timer ; ; Keyboard handler ; CLICK *= *+1 ; key click counter LENGTH *= *+1 ; line length register ; ; DLI control ; DLICOL *= *+1 ; DLI color index ; ; Screen clearing ; CLPOINT *= *+2 ; screen clear pointer CINDEX *= *+1 ; window clear index ; ; Parser ; PBUFF *= *+3 ; parsing buffer PDEX *= *+1 ; scanning index LBREAK *= *+1 ; pos. of space char VCODE *= *+1 ; verb code # UCODE *= *+1 ; untranslated noun code # NCODE *= *+1 ; translated noun code # DOVECT *= *+2 ; verb execution vector CURVECT *= *+6 ; current room vectors CUROBJS *= *+6 ; current room objects NEWPLACE *= *+1 ; next room code # VPNT *= *+2 ; addr of current v-buffer OPNT *= *+2 ; addr of current o-buffer INVPOS *= *+1 ; position in inventory buffer ROOMPOS *= *+1 ; position in room buffer ANY? *= *+1 ; flag for empty room/inv VLAST *= *+1 ; last verb ULAST *= *+1 ; last noun ; ; Event counter ; EBUFF *= *+5 ; printing buffer ; ; INITIALIZATION ; -------------- ; *= $1F80 ; ENTRY LDX #0 STX COLDST INX ; = 1 STX BOOT? JSR MOVESET ; redefine char set JSR SIOINV ; for sound init JMP TITLE ; ; CUSTOM DISPLAY LIST ; ------------------- DLIST .BYTE $70,$70,$70,$70 ; blank 32 lines .BYTE $42, SCREEN ; text w/LMS .BYTE $90,$10 ; blank 4 w/DLI .BYTE $02 ; text (location) .BYTE $90,$10 ; blank 4 w/DLI .BYTE $02 ; text (exits) .BYTE $90,$10 ; blank 4 w/DLI .BYTE $02,$02,$02,$02,$02,$02 ; text (v-items) .BYTE $90,$10 ; blank 4 w/DLI .BYTE $02,$02 ; text (events) .BYTE $90,$10 ; blank 4 w/DLI .BYTE $02,$02 ; text (response) .BYTE $80,$80,$10 ; blank 4 w/DLIs .BYTE $02,$02,$02,$02,$02,$02 ; text (i-items) .BYTE $70 ; blank 8 .BYTE $41, DLIST ; JVB ; ; TITLE SCREEN ; ------------ TITLE LDX #$FF TXS JSR NEWSCREEN ; reset E: POSITION 12,6 PRINT T0 ; "Clayton Walnum's" POSITION 22,7 PRINT T1 ; "ONE FOR THE ROAD" POSITION 8,9 PRINT T2 ; "(C)1985 ANALOG Computing" ; STARTOP POSITION 5,16 PRINT T3 ; "Press START to play new game" ;!!!!!!!! INVERSE CHARS !!!!!!!! POSITION 3,18 PRINT T4 ; "Press OPTION to restore old game" ;!!!!!!!! INVERSE CHARS !!!!!!!! ; LDA #6 STA EDLIST+12 ; modify STA EDLIST+13 ; display list ; LDA #$22 STA SDMCTL ; restore screen JSR BEEP ; ; Wait for selection ; POLL LDA CONSOL CMP #7 ; scan until a BEQ POLL ; key is pressed LETGO LDX CONSOL CPX #7 BNE LETGO CMP #6 ; START pressed? BEQ NEWGAME ; yes, do a new game CMP #3 ; OPTION pressed? BEQ RESTORE ; yes, restore old game BADPOLL JSR BOOP ; else JMP POLL ; resume scan ; ; Start new game ; NEWGAME JSR INITDATA JMP PLAYSCREEN ; ; Restore a previous game ; RESTORE POSITION 5,20 PRINT T5 ; "Restore from Disk or Tape?" JSR BEEP DORT JSR GETKEY CMP #'D ; disk? BEQ GETDISK CMP #'C ; tape? BEQ GETAPE DORTERR JSR CLOSE1 JSR BOOP JMP DORT ; ; Get game from disk ; GETDISK JSR DPOINT JMP READOPEN ; ; Get game from tape ; GETAPE JSR TPOINT ; READOPEN LDA #3 ; OPEN command STA ICCOM,X LDA #4 ; READ STA ICAUX1,X LDA #0 STA ICAUX2,X JSR CIOV BMI DORTERR ; ; Get game data thru IOCB #1 ; GETDATA LDX #$10 LDA # GAMEDATA STA ICBADR+1,X LDA #$51 STA ICBLEN,X LDA #$01 STA ICBLEN+1,X LDA #7 ; GET RECORD STA ICCOM,X JSR CIOV BMI DORTERR JSR CLOSE1 ; ; PLAYSCREEN INIT ; --------------- PLAYSCREEN JSR NEWSCREEN ; reset E: ; ; Enable custom display list ; LDA # DLIST STA SDLSTL+1 ; ; Print title & labels ; PRINT T6 ; "ONE FOR THE ROAD EVENT #" LDA #12 ; set right margin STA RMARGN ; for wraparound PRINT T7 ; "LOCATION/EXITS" PRINT T8 ; "VISIBLE ITEMS" JSR BAR JSR BAR JSR BAR JSR BAR ; 4 blank bars JSR SAYWHAT ; "WHAT" PRINT T11 ; "HAPPENS/YOUR RESPONSE" JSR SAYWHAT ; "WHAT" PRINT T12 ; "YOU ARE CARRYING" JSR BAR JSR BAR ; more blank bars LDA #39 STA RMARGN ; reset ; LDA #$0C ; white STA PCOLR0 ; cursor ; ; Setup P/M borders & mask ; LDA #48 STA HPOSP1 ; position left LDA #202 ; and STA HPOSP2 ; right borders LDA #64 ; and STA HPOSP3 ; title cover LDX #255 STX GRAFP1 ; set up STX GRAFP2 ; side borders and STX GRAFP3 ; title mask INX ; = 0 STX SIZEP0 ; set cursor width INX ; = 1 STX GPRIOR ; set player priority LDA #3 STA SIZEP1 ; set border STA SIZEP2 ; and mask STA SIZEP3 ; widths ; LDA #$F0 ; init STA CSHAPE ; cursor shape LDA #30 ; and STA BLINK ; blink timer ; LDA #13 STA LMARGN ; init left margin ; LDY # IMMVBI ; specifying LDA #6 ; immediate-mode JSR SETVBV ; LDA # DLI ; we put our STA VDSLST+1 ; DLI service routine LDA #$C0 ; set bits 6 & 7 of NMIEN STA NMIEN ; to enable DLIs and VBIs ; LDA PLACE JMP REENTRY ; ; EVENT GENERATOR ; --------------- ; NEXTEVENT LDX #$FF ; empty stack TXS ; just in case! JSR SHOWEV ; show event # INC EVENT ; update BNE HITROCKS ; event INC EVENT+1 ; counter ; ; Handle rocks ; HITROCKS LDA PLACE CMP #3 BCC R1 JMP EXPLODE R1 DEC ROCKCNT LDA ROCKCNT BNE EXPLODE JSR NEWSCREEN POSITION 9,3 PRINT T77 ; "Crashing into the rocks" JMP KILLS ; ; Handle explosion ; EXPLODE LDA BLAST ; counter set? BEQ CHESTRTN ; no DEC BLAST ; -1 from counter LDA BLAST ; time to explode? BNE CHESTRTN ; no LDA PLACE CMP DPLACE ; player in same room as dynamite? BEQ EXP4 ; yes, too bad! LDA #25 ; dynamite JSR OWNIT? BEQ EXP4 ; deep trouble! LDA DPLACE ; room with dynamite ASL A ; * 2 ; calculate position STA NCODE ; in objects buffer ASL A ; * 4 CLC ADC NCODE ; *2 + *4 = *6 ADC #5 TAY ; use Y as index EXP0 LDA OBJECTS,Y ; get object CMP #25 ; dynamite? BEQ EXP1 ; sure is! DEY BNE EXP0 ; try next object EXP1 LDA DPLACE CMP #9 ; explosion in room 9? BNE EXP3 ; nope LDA #0 ; cave STA OBJECTS,Y ; put in room 9 LDA #10 ; new room vector STA VECTORS+57 EXP2 POSITION 13,10 PRINT T48 ; "Booooommmmm!!" JSR BOOM JMP CHESTRTN EXP3 LDA #255 STA OBJECTS,Y ; get rid of dynamite BNE EXP2 EXP4 JSR NEWSCREEN POSITION 12,3 PRINT T73 ; "Huge explosion" JSR BOOM JMP KILLS ; ; handle chest ; CHESTRTN LDA CHECNT CMP #255 ; chest already placed? BEQ MATCHRTN ; yes CMP #0 ; time for chest to show up? BNE CRTN1 ; nope LDA PLACE ; current room CMP #3 ; is it room 3? BEQ MATCHRTN ; yes LDY #23 ; point to room 3 object buffer CRTN LDA OBJECTS,Y CMP #255 ; got space? BEQ CRTN0 ; yes! DEY CPY #17 ; end of room 3 buffer? BNE CRTN ; no, try again BEQ MATCHRTN ; no space yet CRTN0 LDA #2 ; chest STA OBJECTS,Y ; put in room CRTN1 DEC CHECNT ; ; handle matches ; MATCHRTN LDA LIT ; match lit? BEQ DRNKRTN ; nope DEC LITCNT ; -1 from counter BNE DRNKRTN ; still lit LDA #0 STA LIT ; match goes out POSITION 13,10 PRINT T29 ; "Match goes out" ; ; handle liquid ; DRNKRTN LDA DRINK ; drank liquid? BEQ PARSER ; no DEC DRINK ; yes, decrement counter LDA DRINK ; time up? BNE PARSER ; no, whew! JSR NEWSCREEN POSITION 11,3 PRINT T32 ; "Strange liquid" JMP KILLS ; ; INPUT PARSER ; ------------ ; PARSER LDA #$22 STA SDMCTL JSR GETLINE ; put line into INLINE JSR CLWH LDX LENGTH CPX #1 ; if length is 1 BNE DOCLAUSE ; check for legality ; ; Check for a legal single-char command ; LDA INLINE ; get the character LDX #8 ; init search index LEGSING CMP SCOMS,X BEQ EXSING ; matched! go do it DEX ; otherwise BPL LEGSING ; keep searching JSR SYNERR ; error, so print PRINT T14 ; "Invalid command" JMP BADPARSE ; and try again ; ; Execute a single-char command ; EXSING LDA SVECTL,X ; fetch the lsb STA DOVECT ; and LDA SVECTH,X ; msb of the STA DOVECT+1 ; execution addr JMP (DOVECT) ; and do it! ; ; Find the 1st space character ; in the user's response ; DOCLAUSE LDA #SPACE STA PBUFF+1 STA PBUFF+2 LDX #1 FIND1 LDA INLINE,X ; length is in X CMP #SPACE ; is it a space? BEQ ENDV ; yes! INX ; else keep scanning CPX LENGTH BCC FIND1 BADVERB JSR SYNERR ; verb is no good, so print PRINT T15 ; "Verb not recognized" JMP BADPARSE ; and try again ; ; Space char found, so record its ; position and move the first half ; of the clause into the parsing buffer ; ENDV STX LBREAK CPX #2 BCC TOVB LDX #2 TOVB LDA INLINE,X STA PBUFF,X DEX BPL TOVB ; ; Check for a legal verb ; LDX #0 ; init verb index STX VCODE VNEXT STX PDEX LDY #0 ; init buffer char index VSCAN LDA PBUFF,Y ; get a char from buffer CMP VERBS,X ; match? BNE NEXTRY ; nope - try another verb INX INY CPY #3 BCC VSCAN ; if all 3 chars match BCS LEGALV ; the verb is legal NEXTRY INC VCODE LDX PDEX INX INX INX CPX #NV*3+3 ; out of verbs? BCC VNEXT ; nope - keep scanning BCS BADVERB ; else verb is worthless ; ; Verb is legal, so fetch its execution ; vector ; ; Move the second half of the ; clause into the parsing buffer ; LEGALV LDX LBREAK ; fetch pos. of space char INX ; plus 1 LDY #0 ; init buffer char index MOVEN LDA INLINE,X ; fetch character STA PBUFF,Y ; stuff into buffer INX INY CPY #3 ; until 3 characters BCC MOVEN ; have been moved ; ; Check for a legal noun ; LDX #0 ; init noun index STX UCODE NNEXT STX PDEX LDY #0 ; init buffer char index NSCAN LDA PBUFF,Y ; get a char from buffer CMP NOUNS,X ; match? BNE NEXTRY2 ; nope - try another noun INX INY CPY #3 BCC NSCAN ; if all 3 chars match BCS LEGALN ; the noun is legal NEXTRY2 INC UCODE LDX PDEX INX INX INX CPX #NN*3+3 ; out of nouns? BCC NNEXT ; nope - keep scanning JSR SYNERR ; else noun is garbage PRINT T16 ; "Bad noun" JMP BADPARSE ; ; Noun's code # is in UCODE; ; verb's code # is in VCODE; ; verb execution addr is in DOVECT ; LEGALN LDA VCODE ; fetch STA VLAST ASL A ; execution addr TAX ; and LDA VVECTS,X ; save it STA DOVECT ; in DOVECT INX LDA VVECTS,X STA DOVECT+1 LDA UCODE STA ULAST TAX LDA NTRANS,X ; translate noun STA NCODE JMP (DOVECT) ; execute verb ; ; EXECUTE SINGLE-CHAR COMMANDS ; ---------------------------- ; ; COMMAND VECTOR TABLES ; --------------------- SVECTL .BYTE DOM, >DOM, >DOM, >DOM, >DOM .BYTE >DOM, >DOQ, >DOX, >DOA ; ; HANDLE "Q" (QUIT) ; ----------------- DOQ POSITION 13,12 PRINT T19 ; "Type Y to quit game:" POSITION 34,12 STX CURSEN ; enable cursor JSR BEEP JSR GETKEY CMP #'Y BEQ DOQUIT LDX #12 JSR ERASE JMP BADPARSE DOQUIT JMP TITLE ; ; HANDLE MOVEMENT ; --------------- ; ENTRY: Vector (0-5) in X ; DOM LDA CURVECT,X BPL EXMOVE CANTGO PRINT T18 ; "You can't go that way." JMP BADPARSE EXMOVE CLD ; for safety STA NEWPLACE ; save destination CMP #2 ; going to room 2? BNE EXMV0 ; no LDA INFLATE ; raft inflated? BEQ EXMV3 ; no LDX RAFTIN ; raft in the water? BEQ EXMV3 ; no BNE EXMV2 EXMV0 CMP #1 ; going to room 1? BNE EXMV1 ; no LDX INFLATE ; raft inflated? BEQ EXMV2 ; no LDA #22 ; raft JSR OWNIT? BEQ EXMV4 EXMV1 CMP #9 ; going to room 9? BNE EXMV2 ; no LDA SNAKE ; snake dead? BNE EXMV2 ; yes PRINT T46 ; "Snake won't let you!" JMP GOODPARSE EXMV2 JSR SAVELOC ; save status LDA NEWPLACE ; get destination, STA PLACE ; make it current, and REENTRY JSR BPOINT ; point to the new buffers ; ; Get new buffer data ; LDY #5 RLOOP LDA (VPNT),Y STA CURVECT,Y LDA (OPNT),Y STA CUROBJS,Y DEY BPL RLOOP ; ; Refresh screen ; SHOWPLACE LDX #1 JSR ERASE ; clear location window POSITION 13,1 LDX PLACE ; get loc # JSR CHGCLR ; set screen colors LDA RDLS,X ; fetch lsb and LDY RDHS,X ; msb of text addr and JSR EPRINT ; print it ; JSR SHOWVIS ; display visible items JSR SHOWVECTS ; display new vectors JSR SHOWINV ; show inventory JMP POKAY ; congratulations! EXMV3 JSR NEWSCREEN POSITION 9,3 PRINT T71 ; "Storm tossed ocean" JMP KILLS EXMV4 PRINT T38 ; "Raft's too big" JMP GOODPARSE ; ; POINT TO NEW BUFFERS ; -------------------- ; ENTRY: Buffer # (0-23) in A ; BPOINT ASL A ; * 2 STA NCODE ; save it ASL A ; * 4 CLC ADC NCODE ; *2 + *4 = *6 STA NCODE ; save it CLC ADC # VECTORS ADC #0 STA VPNT+1 CLC LDA NCODE ADC # OBJECTS ADC #0 STA OPNT+1 RTS ; ; HANDLE "X" (SAVE GAME) ; ---------------------- DOX JSR SAVELOC ; save current status JSR NEWSCREEN POSITION 5,11 PRINT T82 ; "Save game to Disk or Cassette?" LDA #$22 STA SDMCTL JSR BEEP SAVEPOLL JSR GETKEY CMP #'D BEQ DSAVE CMP #'C BEQ CSAVE BADWRITE JSR CLOSE1 JSR BOOP JMP SAVEPOLL ; ; Save to disk ; DSAVE JSR DPOINT JMP GSAVE ; ; Save to cassette ; CSAVE JSR TPOINT ; GSAVE LDA #3 STA ICCOM,X LDA #8 STA ICAUX1,X LDA #0 STA ICAUX2,X JSR CIOV BMI BADWRITE ; ; Write out game data ; WRITE LDX #$10 LDA # GAMEDATA STA ICBADR+1,X LDA #$51 STA ICBLEN,X LDA #$01 STA ICBLEN+1,X LDA #11 STA ICCOM,X JSR CIOV BMI BADWRITE JSR CLOSE1 JMP PLAYSCREEN ; ; HANDLE "A" (AGAIN) ; ------------------ DOA LDA VLAST ; restore old verb STA VCODE LDA ULAST ; and noun STA UCODE JMP LEGALN ; and do it again! ; ; SAVE LOC STATUS ; --------------- SAVELOC LDA PLACE JSR BPOINT LDY #5 SLOOP LDA CURVECT,Y STA (VPNT),Y LDA CUROBJS,Y STA (OPNT),Y DEY BPL SLOOP RTS ;